2 Binary Search & LogN Algorithm

254. Drop Eggs

https://www.lintcode.com/problem/drop-eggs/description?_from=ladder&&fromId=1

28. Search a 2D Matrix

https://www.lintcode.com/problem/search-a-2d-matrix/description?_from=ladder&&fromId=1

思路1:

  1. find the row index, the last number <= target

  2. find the column index, the number equal to target

public class Solution {
    /**
     * @param matrix: matrix, a list of lists of integers
     * @param target: An integer
     * @return: a boolean, indicate whether matrix contains target
     */
    public boolean searchMatrix(int[][] matrix, int target) {
        // write your code here
        if(matrix == null || matrix.length == 0) return false;
        int left = 0, right = matrix[0].length - 1;
        int row = findRow(matrix, target);
        if(matrix[row][0] > target || matrix[row][right] < target) {
            return false;
        } 
        while(left + 1 < right) {
            int mid = left + (right - left) / 2;
            if(matrix[row][mid] == target) {
                return true;
            } else if(matrix[row][mid] > target) {
                right = mid;
            } else {
                left = mid;
            }
        }
        if(matrix[row][left] == target || matrix[row][right] == target) {
            return true;
        } else {
            return false;
        }
    }
    
    public int findRow(int[][] matrix, int target) {
        int top = 0, bottom = matrix.length - 1, right = matrix[0].length - 1;
        while(top + 1 < bottom) {
            int mid = top + (bottom - top) / 2;
            if(matrix[mid][right] == target) {
                return mid;
            } else if(matrix[mid][right] > target) {
                bottom = mid;
            } else {
                top = mid;
            }
        }
        if(matrix[top][right] >= target) {
            return top;
        } else {
            return bottom;
        }
    }
}

思路2:

1. 可以看作是一个有序数组被分成了n段,每段就是一行。因此依然可以二分求解。

对每个数字,根据其下标 i,j 进行编号,每个数字可被编号为 0 ~ n *(n - 1)

2. 相当于是在一个数组中的下标,然后直接像在数组中二分一样来做。取得 mid 要还原成二维数组中的下标,i = mid / n, j = mid % n

3. int start = 0, end = row * row * column - 1;

int number = matrix[mid / column][mid % column];

// Binary Search Once
public class Solution {
    /**
     * @param matrix, a list of lists of integers
     * @param target, an integer
     * @return a boolean, indicate whether matrix contains target
     */
    public boolean searchMatrix(int[][] matrix, int target) {
        // write your code here
        if(matrix == null || matrix.length == 0){
            return false;
        }
        
        if(matrix[0] == null || matrix[0].length == 0){
            return false;
        }
        
        int row = matrix.length;
        int column = matrix[0].length;
        
        int start = 0, end = row * column - 1;
        while(start <= end){
            int mid = start + (end - start) / 2;
            int number = matrix[mid / column][mid % column];
            if(number == target){
                return true;
            }else if(number > target){
                end = mid - 1;
            }else{
                start = mid + 1;
            }
        }
        
        return false;
        
    }
}

14. First Position of Target 

https://www.lintcode.com/problem/first-position-of-target/description?_from=ladder&&fromId=1

思路:这道题很简单。套用二分法的模版即可

 1 public class Solution {
 2     /**
 3      * @param nums: The integer array.
 4      * @param target: Target to find.
 5      * @return: The first position of target. Position starts from 0.
 6      */
 7     public int binarySearch(int[] nums, int target) {
 8         // write your code here
 9         if(nums == null || nums.length == 0) return -1;
10         int start = 0, end = nums.length - 1;
11         while(start + 1 < end) {
12             int mid = start + (end - start) / 2;
13             if(nums[mid] >= target) {
14                 end = mid;
15             } else {
16                 start = mid;
17             }
18         }
19         if(nums[start] == target) {
20             return start;
21         }
22         if(nums[end] ==  target) {
23             return end;
24         }
25         return -1;
26     }
27 }

414. Divide Two Integers

https://www.lintcode.com/problem/divide-two-integers/description?_from=ladder&&fromId=1

1. 凡是要移位,要做的第一件事就是把 int 转换成 long,为了防止移位时溢出。

2. 基本思路是利用减法,看看被除数可以减去多少次除数。使用倍增的思想优化,可以将减法的次数优化到对数的时间复杂度。

3. 我们将除数左移一位(或加上它自己),即得到了二倍的除数,这时一次相当于减去了两个除数,通过不断倍增,时间复杂度很优秀。

4. 与此同时,还需要一个变量记录此时的除数是最初除数的多少倍,每次减法后都加到结果上即可。

 1 public class Solution {
 2     /**
 3      * @param dividend: the dividend
 4      * @param divisor: the divisor
 5      * @return: the result
 6      */
 7     public int divide(int dividend, int divisor) {
 8         // write your code here
 9         if(divisor == 0) {
10             return dividend >= 0 ? Integer.MAX_VALUE : Integer.MIN_VALUE;
11         }
12         if(dividend == 0) {
13             return 0;
14         }
15         if(divisor == -1 && dividend == Integer.MIN_VALUE) {
16             return Integer.MAX_VALUE;
17         }
18         boolean isNegative = ((divisor > 0 && dividend < 0) || (divisor < 0 && dividend > 0)) ? true : false;
19         long divisorL = Math.abs((long)divisor);
20         long dividendL = Math.abs((long)dividend);
21         int result = 0;
22         while(dividendL >= divisorL) {
23             int shift = 0;
24             while(dividendL >= (divisorL << shift)) {
25                 shift++;
26             }
27             result += 1 << (shift - 1);
28             dividendL -= divisorL << (shift - 1);
29         }
30         if(isNegative) {
31             return result * (-1);
32         }
33         return result;
34     }
35 }

61. Search for a Range

https://www.lintcode.com/problem/search-for-a-range/description?_from=ladder&&fromId=1

这道题同样很简单,套用模版即可。

 1 public class Solution {
 2     /**
 3      * @param A: an integer sorted array
 4      * @param target: an integer to be inserted
 5      * @return: a list of length 2, [index1, index2]
 6      */
 7     public int[] searchRange(int[] A, int target) {
 8         // write your code here
 9         if(A == null || A.length == 0) return new int[]{-1, -1};
10         int start = findStart(A, target);
11         int end = findEnd(A, target);
12         return new int[]{start, end};
13         
14     }
15     
16     public int findStart(int[] A, int target) {
17         int start = 0;
18         int end = A.length - 1;
19         while(start + 1 < end) {
20             int mid = start + (end - start) / 2;
21             if(A[mid] < target) {
22                 start = mid;
23             } else {
24                 end = mid;
25             }
26         }
27         if(A[start] == target) {
28             return start;
29         } 
30         if(A[end] == target) {
31             return end;
32         }
33         return -1;
34     }
35     
36     public int findEnd(int[] A, int target) {
37         int start = 0;
38         int end = A.length - 1;
39         while(start + 1 < end) {
40             int mid = start + (end - start) / 2;
41             if(A[mid] <= target) {
42                 start = mid;
43             } else {
44                 end = mid;
45             }
46         }
47         if(A[end] == target) {
48             return end;
49         }
50         if(A[start] == target) {
51             return start;
52         } 
53         return -1;
54     }
55 }
原文地址:https://www.cnblogs.com/jenna/p/10733567.html