如何保证你的二分查找一遍就过

206 阅读2分钟

简介

二分查找是在有序数组中查找指定元素的算法,是在计算机科学中应用最广泛的算法之一,如二叉搜索树等。

示例

在一个升序数组中,查找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要不要这两个情况,可以解决很多在变形的二分查找的题目中对边界值的不确定的问题。后面我再补充一些复杂的二分查找的题目来佐证此概念。