简介
二分查找是在有序数组中查找指定元素的算法,是在计算机科学中应用最广泛的算法之一,如二叉搜索树等。
示例
在一个升序数组中,查找target,若找到返回下标,未找到返回-1。
代码:
public int search(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
while (left <= right) {
int mid = (left + right) >> 1;
if (nums[mid] == target) {
return mid;
}
if (nums[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return -1;
}
思路很清晰,所以代码比较简单。其优势就在于:遍历查找的话,时间复杂度是O(N),而二分查找的时间复杂度是O(logN),这大大提高了查询速度。
重点
二分查找中有两个重点,如果可以注意到的话,以后写相似的二分查找的题目,基本手拿把攥,一遍过掉所有case,不需要在用极端case进行调试排查。
一. 等号要不要
一般来说while循环里的条件就是:left < right,或者left <= right。有时候会比较迷糊,什么时候用等号,什么时候不用。
这个我们可以用长度为1的数组来判断,以二分查找为例,left = 0, right = length - 1,假设数组长度为1的话,那么如果没有等号的话,就直接不进入循环,返回-1了,数组中唯一的元素没有被判断到,所以这里需要加上等号。在一些变形的二分查找题目中,也可以类似处理。
二. 1要不要
在缩小查询范围时,一般场景下的情况就是 left = mid,left = mid + 1,right = mid,right = mid - 1。1要不要这个也需要根据题目的具体情况进行分析,如果赋值不准确的话,容易进入死循环或者边界值没有被判断到。
这个可以用边界值来判断,还是以二分查找为例,这里我们在前面确定了nums[mid] != target了,说明mid这个边界值不可能在搜索结果内,所以就可以大胆抛弃,使用left = mid + 1,right = mid - 1。
总结
写代码时考虑到等号要不要,1要不要这两个情况,可以解决很多在变形的二分查找的题目中对边界值的不确定的问题。后面我再补充一些复杂的二分查找的题目来佐证此概念。