二分法总结

待补充。

Leetcode上Binary Search题目(按frequency排序):
4 Median of Two Sorted Arrays
50 Pow(x, n)
153 Find Minimum in Rotated Sorted Array
33 Search in Rotated Sorted Array
69 Sqrt(x)
29 Divide Two Integers
162 Find Peak Element
278 First Bad Version
34 Search for a Range
35 Search Insert Position
74 Search a 2D Matrix
240 Search a 2D Matrix II
154 Find Minimum in Rotated Sorted Array II
81 Search in Rotated Sorted Array II
222 Count Complete Tree Nodes
287 Find the Duplicate Number
230 Kth Smallest Element in a BST
209 Minimum Size Subarray Sum
174 Dungeon Game
300 Longest Increasing Subsequence
275 H-Index II
167 Two Sum II - Input array is sorted
270 Closest Binary Search Tree Value
302 Smallest Rectangle Enclosing Black Pixels

本文题目目录:
1.search-a-2d-matrix
2.search-for-a-range
3.sqrtx
4.search-insert-position
5.find-minimum-in-rotated-sorted-array
6.find-minimum-in-rotated-sorted-array-ii
7.search-in-rotated-sorted-array
8.search-in-rotated-sorted-array-ii
9.find-peak-element

诀窍:
永远返回l法。初始的l和r取可能的最左(含)和最右(含)。永远让l处于可能为结果的那个位置(这样r自然也处于)。l = m的时候m = (l+r)/2+1, l = m+1的时候m = (l+r)/2。
如果发现不对的地方欢迎指正。

1.search a 2d matrix
l = mid+1而非mid,否则会陷入死循环。

class Solution {
public:
    bool searchMatrix(vector>& matrix, int target) {
        if(matrix.size() == 0 || matrix[0].size() == 0) return false;
        int m = matrix.size();
        int n = matrix[0].size();
        int l = 0;
        int r = m * n - 1;
        int x,y;
        while(l < r) {
            int mid = l + (r - l) / 2;
            x = mid/n;
            y = mid%n;
            if(matrix[x][y] < target) {
                l = mid + 1;
            } else {
                r = mid;
            }
        }
        x = l/n;
        y = l%n;
        return matrix[x][y] == target;
    }
};

2.search for a range
找左侧:if(A[m] 找右侧:if(A[m]<=target) 目标肯定在m往后(含),l=m,所以m要+1,否则死循环

class Solution {
public:
    vector searchRange(vector& A, int target) {
        int n = A.size();
        int lres,rres;
        //find lres
        int l = 0;
        int r = n - 1;
        while(l < r) {
            int m = l + (r - l) / 2;
            if(A[m] < target) {
                l = m + 1;
            } else {
                r = m;
            }
        }
        lres = l;
        if(A[lres] != target) {
            return {-1, -1};
        }
        //find rres
        l = 0;
        r = n - 1;
        while(l < r) {
            int m = l + (r - l) / 2 + 1;
            if(A[m] <= target) {
                l = m;
            } else {
                r = m - 1;
            }
        }
        rres = l;
        return {lres, rres};
    }
};

3.sqrtx
类似上一题的find rres。
if(m <= x/m) 那么目标肯定在m往右(含),所以m要+1,l=m

class Solution {
public:
    int mySqrt(int x) {
        int l = 0;
        int r = x;
        while(l < r) {
            int m = l + (r - l) / 2 + 1;
            if(m <= x/m) {
                l = m;
            } else {
                r = m - 1;
            }
        }
        return l;
    }
};

4.search insert position
初始化的时候注意,最左可能为0,最右可能为n而不是n-1。
注意题意在nums[m] ==target时插入在m的位置。如果要插入到后面,就要让if(nums[m] < target)改为<=。

class Solution {
public:
    int searchInsert(vector& nums, int target) {
        int n = nums.size();
        int l = 0;
        int r = n;
        while(l < r) {
            int m = l + (r - l)/2;
            if(nums[m] < target) {
                l = m + 1;
            } else {
                r = m;
            }
        }
        return l;
    }
};

5.find minimum in rotated sorted array
类似上面,比较简单。

class Solution {
public:
    int findMin(vector& nums) {
        int n = nums.size();
        int l = 0;
        int r = n - 1;
        while(l < r) {
            int m = l + (r - l) / 2;
            if(nums[m] < nums[r]) {
                r = m;
            } else {
                l = m + 1;
            }
        }
        return nums[l];
    }
};

6.find minimum in rotated sorted array ii

class Solution {
public:
    int findMin(vector& nums) {
        int n = nums.size();
        if(n == 0) return -1;
        int l = 0;
        int r = nums.size() - 1;
        while(l < r) {
            int m = l + (r - l) / 2;
            if(nums[m] > nums[r]) {
                l = m + 1;
            } else if(nums[m] < nums[r]){
                r = m;
            } else {
                r--;
            }
        }
        return nums[l];
    }
};

改进else里面:

    if(nums[l] < nums[m])
        r = m - 1;
    else if(nums[l] > nums[m])
        r = m;
    else 
        r--;

7.search in rotated sorted array
思路1,直接做。思路2,先找到pivot,再做普通搜索(略)。
思路1:

class Solution {
public:
    int search(vector& nums, int target) {
        int l = 0;
        int r = nums.size() - 1;
        while(l < r) {
            int m = l + (r - l) / 2;
            if(nums[m] > nums[r]) {
                if(target >= nums[l] && target <= nums[m]) {
                    r = m;
                } else {
                    l = m + 1;
                }
            } else if(nums[m] < nums[r]) {
                if(target > nums[m] && target <= nums[r]) {
                    l = m + 1;
                } else {
                    r = m;
                }
            }
        }
        if(nums[l] == target) 
            return l;
        return -1;
    }
};

8.search in rotated sorted array ii
懒惰解法:
直接在上面的解法下面加一个else r--。内部加一个判断减少循环次数。

class Solution {
public:
    bool search(vector& nums, int target) {
        int l = 0;
        int r = nums.size() - 1;
        while(l < r) {
            int m = l + (r - l) / 2;
            if(nums[m] == target) return true;
            if(nums[m] > nums[r]) {
                if(target >= nums[l] && target <= nums[m]) {
                    r = m;
                } else {
                    l = m + 1;
                }
            } else if(nums[m] < nums[r]) {
                if(target > nums[m] && target <= nums[r]) {
                    l = m + 1;
                } else {
                    r = m;
                }
            } else {
                r--;
            }
        }
        return nums[l] == target;
    }
};

9.Find Peak Element
返回随意一个的程序如下。如果让我找最左侧的那个呢?只能顺序找。

class Solution {
public:
    int findPeakElement(vector& nums) {
        int l = 0;
        int r = nums.size() - 1;
        while(l < r) {
            int m = l + (r - l) / 2;
            if(nums[m] < nums[m+1]) {
                l = m + 1;
            } else {
                r = m;
            }
        }
        return l;
    }
};

你可能感兴趣的:(二分法总结)