Binary Search 二分查找法
February 15, 2022
4554
前言
纠结症患者的福音,也算是分治策略的一种吧,逐渐把大问题化小,小问题化无。
最早接触二分查找法,是小时候的一道数学题。问有n个球,其中有一个球是残次品,质量略小于其他的球,你有一个天平,没有砝码和刻度,请问,你怎样可以最快找出这个残次球。
二分法的思想很简单,但是有很多细节需要考虑。常常同一道题,用二分法的思想,可以写出不同的解法,而且殊途同归,都可以解决问题。一开始我也常常很苦恼,直到真正找到其中的奥秘,有一种拨云见日的感觉。现在遇到二分题,我也不敢说一定能百分百秒杀,至少经过练习,心理上会自信很多。
介绍
二分查找的基本思想是将n个顺序元素分成大致相等的两部分,将查找目标值与分隔中间值进行比较,选择中间值的两边,进行比较,直到范围缩小为1。时间复杂度为O(lgN),空间复杂度为O(1)。
自用模版
我在前沿里说了,二分的模版有很多,这里是我最顺手,最常用的模版,它找的是第一个大于等于k的数在数组中的位置。
1 |
|
细节
- 选择左右指针
我习惯用l和r,也有人用l(low)和h(high)来代表左右指针。
左指针一般都是0起步,没什么异议,但是对于右指针,我们有的时候会选择为数组的长度n,而不是最后一个元素的index。
这个选择,取决于答案的范围。例如,最大可能答案是n,那么我们的右指针应当从数组的长度n开始。 - 中间元素index mid的计算
一般来说计算方式有如下两种:如果区间范围内的元素总数为奇数,那么两种方式计算出的mid和mid2都为中间元素,所以并没有区别。1
2
3
4
5
6
7// when odd, return the only mid
// when even, return the lower mid
int mid = lo + ((hi - lo)/2);
// when odd, return the only mid
// when even, return the upper mid
int mid2 = lo + ((hi - lo + 1) / 2);
但是,如果区间范围内的元素总数为偶数,那么在选取中间元素时,我们就会有较小元素mid,和较大元素mid2,两种选择方式了。
此外,为了防止溢出,我们一般不会直接把左右元素相加除以2,而是写成 l+差 这样形式的。 - 左右指针的移动 = if条件
写我们100%确定的条件1
2
3
4
5
6
7
8
9
10
11if (100% sure logic) {
left = mid + 1; // 100% sure target is to the right of mid
} else {
right = mid;
}
if (100% sure logic) {
right = mid - 1; // 100% sure target is to the left of mid
} else {
left = mid;
} - 循环的出口 = while条件
有的人会使用l <= r
,来作为while的条件。但是,在我的模版中,我们始终使用l < r
来作为循环的出口,因为这样我们可以保证,当循环结束时,l和r一定相等。如果需要判断target不存在情况,那么我们可以在循环外判断。 - 防止无限循环
这是一个新手经常会遇到的问题。为啥我的二分法没法结束呢?这时候,你需要检查一下,你的mid值取的是上边界,还是下边界,如果像下面的代码,你的mid值是上边界,而移动左右指针时,又是保持左边界l不变,移动右边界r,那么你可能就会进入无限循环了。
解决的诀窍是,考虑当左右边界之间,只有2个元素时的情况下,如何退出循环。1
2
3
4
5
6
7
8
9
10// ❌ The following code results in inifite loop
int mid = lo + ((hi - lo)/2); // aka the lower mid
// We should use:
// int mid = lo + ((hi - lo + 1)/2) // aka the upper mid
if (100% sure logic) {
right = mid - 1
} else {
left = mid // <-- note here
}
API 大法
1 |
|
刷题
精选练习
- 704.Binary Search 首选练习,不能更直接了
- 1064.Fixed Point
- 34.Find First and Last Position of Element in Sorted Array
- 33.Search in Rotated Sorted Array
- 34.Find First and Last Position of Element in Sorted Array
更多基础练习
- 35.Search Insert Position 注意左右指针的初始选择
- 69.Sqrt(x) 注意溢出,if条件的选择
- 367.Valid Perfect Square 和上一题很像
- 278.First Bad Version
- 374.Guess Number Higher or Lower
- 704.Binary Search 首选练习,不能更直接了
- 852.Peak Index in a Mountain Array 不错的一题,建议练习
- 1064.Fixed Point 不错的一题,建议练习
- 1099.Two Sum Less Than K 小变体
- 1150.Check If a Number Is Majority Element in a Sorted Array 小变体
- 1337.The K Weakest Rows in a Matrix 坑特别多,值得练习
- 1346.Check If N and Its Double Exist 二分法的典型应用,注意负数
- 74.Search a 2D Matrix
- 1351.Count Negative Numbers in a Sorted Matrix
- 1385.Find the Distance Value Between Two Arrays
- 1539.Kth Missing Positive Number
- 1608. Special Array With X Elements Greater Than or Equal X
- 153.Find Minimum in Rotated Sorted Array
- 162.Find Peak Element
- 167.Two Sum II - Input Array Is Sorted 双指针 + 二分查找,如果你已经想到双指针了,那想想是不是可以结合二分查找缩小指针范围呢?