思路
二分查找的唯一思想:逐步缩小搜索空间
具体做法:根据题意,得到单调性和能够逐步缩小搜索规模的条件,明确每一轮搜索的范围,进而设置能够使左右区间的边界紧缩的条件
细节
1 mid要考虑溢出问题,一般设置为mid = left + (right - left) / 2,有时候考虑到当数组只有两个元素的时候要避免死循环,需要在括号里加一:mid = left + (right - left + 1) / 2,如 LeetCode69. x的平方根 这一题。
2 二分查找并不一定是有序的,只要数组满足某种规律也能使用二分法进行查找。
3 while判断中写成while(left < right),当left = right 时即可退出循环,返回的时候直接返回left即可。但是在LeetCode704.二分查找一题中,当单个元素数组出现,必须考虑left=right情况,将while判断写成while(left <= right),返回满足target = nums[mid]的mid。
目录
题型一:二分求下标(在数组中查找符合条件的元素的下标)
说明:
第 704 题:二分查找的最原始问题,使用两边夹的二分查找方法需要后处理(退出循环以后,还需要判断 left 或 right 位置的值是不是问题的答案);
第 34 题、第 35 题:需要明白这一类问题的共同特点,请见 这里;
第 300 题:特别经典的一道「动态规划」,二分查找的思路基于「动态规划」的状态定义得到,代码很像第 35 题;
第 658 题:这个问题二分的写法需要做复杂的分类讨论,可以放在以后做;
第 4 题:二分查找里最难的问题,重点在于理解:① 为什么是在短数组里找边界;② 深刻理解搜索边界的意义。
题号 链接 题解
704 二分查找(简单)
35 搜索插入位置(简单) 【视频讲解】、文字题解
300 最长上升子序列(中等) 文字题解
34 在排序数组中查找元素的第一个和最后一个位置(简单) 【视频讲解】、文字题解
611 有效三角形的个数 文字题解
658 找到 K 个最接近的元素(中等) 文字题解
436 寻找右区间(中等) 文字题解
1237 找出给定方程的正整数解(中等)
1300 转变数组后最接近目标值的数组和(中等) 文字题解
4 寻找两个有序数组的中位数(困难) 【视频讲解】、文字题解
使用二分查找的前提不一定非要是「有序数组」。旋转有序数组(下表前 4 题)、山脉数组(下表后 2 题)里的查找问题也可以使用「二分查找」。这些问题的解决思路是:利用 局部单调性,逐步缩小搜索区间。
题号 链接 题解
33 搜索旋转排序数组(中等) 文字题解
81 搜索旋转排序数组 II(中等) 文字题解
153 寻找旋转排序数组中的最小值(中等) 文字题解
154 寻找旋转排序数组中的最小值 II(困难) 文字题解
852 山脉数组的峰顶索引(简单)
1095 山脉数组中查找目标值(中等) 【视频讲解】、文字题解
题型二:二分答案(在一个有范围的区间里搜索一个整数)
如果题目要我们找一个整数,这个整数有确定的范围,可以通过二分查找逐渐缩小范围,最后逼近到一个数。
定位一个有范围的整数,这件事情也叫「二分答案」或者叫「二分结果」。如果题目要求的是一个整数,这个整数有明确的范围,可以考虑使用二分查找。
事实上,二分答案是我们最早接触的二分查找的场景。「幸运 52」里猜价格游戏,就是「二分查找」算法的典型应用:先随便猜一个数,如果猜中,游戏结束。如果猜大了,往小猜;如果猜小了,往大猜。
说明:
第 69 题:在一个整数范围里查找一个整数,也是二分查找法的应用场景;
第 275 题:这个问题题解题意得花很多时间,可以跳过不做;
第 278 题:在一个整数范围里查找一个整数,不是在输入数组里使用二分查找。这个问题二分查找的解法很反常规(不应该用时间换空间),知道即可。
题号 链接 题解
69 x 的平方根(简单) 文字题解
287 寻找重复数(中等) 文字题解
374 猜数字大小(简单) 文字题解
275 H指数 II(中等) 文字题解
1283 使结果不超过阈值的最小除数(中等) 文字题解
1292 元素和小于等于阈值的正方形的最大边长(中等)
题型三:二分答案的升级版(每一次缩小区间的时候都需要遍历数组)
说明:这一类问题本质上还是「题型二」(二分答案),但是初学的时候会觉得有一些绕。这一类问题的问法都差不多,关键字是「连续」、「正整数」,请大家注意捕捉题目中这样的关键信息。
这里给出的问题解法都一样,会一题等于会其它题。问题的场景会告诉我们:目标变量和另一个变量有相关关系(一般是线性关系),目标变量的性质不好推测,但是另一个变量的性质相对容易推测(满足某种意义上的单调性)。这样的问题的判别函数通常会写成一个函数的形式。
这一类问题可以统称为「 最大值极小化 」问题,最原始的问题场景是木棍切割问题,这道题的原始问题是「力扣」第 410 题(分割数组的最大值(困难))。
思路是这样的:
分析出题目要我们找一个整数,这个整数有范围,所以可以用二分查找;
分析出 单调性,一般来说是一个变量 a 的值大了,另一个变量 b 的值就变小,而「另一个变量的值」 b 有限制,因此可以通过调整 a 的值达到控制 b 的效果;
这一类问题的题目条件一定会给出 连续、正整数 这样的关键字。如果没有,问题场景也一定蕴含了这两个关键信息。
参考资料:
二分查找之「最大值极小化」相关问题及解题步骤
二分查找之「最大值极小化」例题选讲
以下给出的问题无一例外。
题号 链接 题解
875 爱吃香蕉的珂珂(中等) 文字题解
410 分割数组的最大值(困难) 文字题解
LCP 12 小张刷题计划(中等) 题解在第 410 题题解里
1011 在 D 天内送达包裹的能力(中等)
1482 制作 m 束花所需的最少天数(中等) 题解在第 1300 题题解里
1552 两球之间的磁力(中等)
补充:「力扣」第 209 题:长度最小的子数组(中等),这道题可以使用「前缀和 + 二分查找」或者「滑动窗口」来做,一定要想清楚,为什么可以使用这些方法。
转自https://leetcode-cn.com/problems/search-insert-position/solution/te-bie-hao-yong-de-er-fen-cha-fa-fa-mo-ban-python-/