整数二分

思想

模板

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
bool check(int x) {/* ... */} // 检查x是否满足某种性质

// 区间[l, r]被划分成[l, mid]和[mid + 1, r]时使用:
int bsearch_1(int l, int r)
{
    while (l < r)
    {
        int mid = l + r >> 1;
        if (check(mid)) r = mid;    // check()判断mid是否满足性质
        else l = mid + 1;
    }
    return l;
}
// 区间[l, r]被划分成[l, mid - 1]和[mid, r]时使用:
int bsearch_2(int l, int r)
{
    while (l < r)
    {
        int mid = l + r + 1 >> 1;
        if (check(mid)) l = mid;
        else r = mid - 1;
    }
    return l;
}

数组中数值和下标相等的元素

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
class Solution {
public:
    int getNumberSameAsIndex(vector<int>& nums) {
        int n = nums.size();
        int l =0,r=n-1;
        while(l<=r){
            int mid = (l+r)>>1;
            if(mid==nums[mid]) return mid;
            else if(mid>nums[mid]) l=mid+1;
            else r=mid-1;
        }
        return -1;
    }
};

数字在排序数组中出现的次数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution {
public:
    int getNumberOfK(vector<int>& nums , int k) {
        int res = 0;
        if(nums.size()==0) return 0;
        int l=0,r=nums.size()-1;
        while(l<r){
            int mid = (l+r)>>1;
            if(nums[mid]<k) l=mid+1;
            else r=mid;
        }
        int a = l;
        if(nums[a]!=k) return 0;
        l=0,r=nums.size()-1;
        while(l<r){
            int mid = (l+r+1)>>1;
            if(nums[mid]<=k) l=mid;
            else r=mid-1;
        }
        return r-a+1;
    }
};

0到n-1中缺失的数字

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
class Solution {
public:
    int getMissingNumber(vector<int>& nums) {
        if (nums.empty()) return 0;
        int l =0,r=nums.size()-1;
        while(l<r){
            int mid = l+r>>1;
            if(mid<nums[mid]) r = mid;
            else l=mid+1;
        }
        if(nums[r]==r) r++;
        return r;
    }
};

旋转数组的最小数字

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
class Solution {
public:
    int findMin(vector<int>& nums) {
        int n = nums.size() - 1;
        if (n < 0) return -1;
        while (n > 0 && nums[n] == nums[0]) n -- ;
        if (nums[n] >= nums[0]) return nums[0];
        int l = 0, r = n;
        while (l < r) {
            int mid = l + r >> 1;       // [l, mid], [mid + 1, r]
            if (nums[mid] < nums[0]) r = mid;
            else l = mid + 1;
        }
        return nums[r];
    }
};

不修改数组找出重复的数字

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
class Solution {
public:
    int duplicateInArray(vector<int>& nums) {
        int l = 1, r = nums.size() - 1;
        while (l < r) {
            int mid = l + r >> 1; // 划分的区间:[l, mid], [mid + 1, r]
            int s = 0;
            for (auto x : nums) s += x >= l && x <= mid;
            if (s > mid - l + 1) r = mid;
            else l = mid + 1;
        }
        return r;
    }
};

浮点数二分

模板

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
bool check(double x) {/* ... */} // 检查x是否满足某种性质

double bsearch_3(double l, double r)
{
    const double eps = 1e-6;   // eps 表示精度,取决于题目对精度的要求
    while (r - l > eps)
    {
        double mid = (l + r) / 2;
        if (check(mid)) r = mid;
        else l = mid;
    }
    return l;
}