今天学一个新算法的时候, 突然发现我以前的二分一直有点问题, 虽然以前的写的二分都能AC, 但还是有些问题, 如果题目给出的区间内没有解, 我的二分可能就会出问题. 加上更久之前发现自己三分写法的问题, 感觉自己能有些题目能AC真是运气好, 所以干脆把所有二分三分思路整理一下.
二分和三分总结与误区分析
整数二分
二分的坑点主要在整数的二分, 如果没有写好会出现死循环的问题.
二分的原理是利用区间内值有序的特点, 不断让可行区间减半, 最终可行区间长度减到1得到答案
要保证二分能得到正确答案并且不会死循环, 要保证两个条件:
1. 解一直在可行区间里
2. 每次判断后可行区间都会缩小(特别是左右端点相距为1的时候)
第一点很好保证, 第二点在可行区间长度大于2的时候不会出问题.
但是当可行区间左右端点相距为1的时候, 因为是整数, 所以中间值mid只能只能取得左端点或者右端点. 这时如果没有处理好, 就可能会陷入死循环.
所以重点要考虑的是当左右端点相距为1的时候, 执行判断后, 可行区间是否会缩小.
我们写二分的时候, 可以先保证第一点, 让解一直在可行区间里面, 然后再根据左右端点相距1的时候的情况, 调整mid到底是向上还是向上取整, 是+1还是-1
下面我们看几个常见的二分写法
二分搜索
写法一
在递增数组中寻找等于key值的位置
最初可行区间为[l, r)
循环退出条件为:
1. 找到了key, 直接return返回
2. 可行区间长度变为0, 无解, 退出并循环返回-1
int bsearch(int *a, int l, int r, int key)
{
int mid;
while(l<r)
{
mid = l + (r-l)/2;
if(a[mid] < key) l = mid+1;
else if(a[mid] == key) return