二分模板

  • 有单调性一定可以二分,可以二分的,不一定具有单调性

1.整数二分模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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; //向右逼近时保证+1向上取整
if (check(mid)) l = mid;
else r = mid - 1;
}
return l;
}

// 区间[l, r]被划分成[l, mid - 1]和[mid+1, r]时使用:
int bsearch_3(int l, int r)
{
while(l<=r){
int mid = l+r>>1;
if(check(mid)) return mid;
else if(target > M.get(mid)) r = mid-1;
else l = mid+1;
}
return -1;
}

两个模板的区别:

当target==nums[mid] 时返回 r = mid; 向左逼近,返回左边界

当target==nums[mid] 时返回 l = mid; 向右逼近,返回右边界

2.小数二分模板

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;
}

备注:

  • 搜索时可以用二分也可以用双指针
  • 二分需要对中间值进行比较的情况
  • 双指针需要对两个数的和进行比较的情况