1 Star 0 Fork 332

大宇 / leetcode

forked from doocs / leetcode 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
README.md 3.03 KB
一键复制 编辑 原始数据 按行查看 历史
ylb 提交于 2021-03-30 23:44 . feat: update binary search algorithm

二分查找

二分查找是一种非常高效的查找算法,高效到什么程度呢?我们来分析一下它的时间复杂度。

假设数据大小是 n,每次查找后数据都会缩小为原来的一半,也就是会除以 2。最坏情况下,直到查找区间被缩小为空,才停止。

被查找区间的大小变化为:

n, n/2, n/4, n/8, ..., n/(2^k)

可以看出来,这是一个等比数列。其中 n/(2^k)=1 时,k 的值就是总共缩小的次数。而每一次缩小操作只涉及两个数据的大小比较,所以,经过了 k 次区间缩小操作,时间复杂度就是 O(k)。通过 n/(2^k)=1,我们可以求得 k=log2n,所以时间复杂度就是 O(logn)。

代码示例

注意容易出错的 3 个地方。

  1. 循环退出条件是 low <= high,而不是 low < high
  2. mid 的取值,可以是 mid = (low + high) / 2,但是如果 low 和 high 比较大的话,low + high 可能会溢出,所以这里写为 mid = (low + high) >>> 1
  3. low 和 high 的更新分别为 low = mid + 1high = mid - 1

Java

非递归实现:

public class BinarySearch {

    private static int search(int[] nums, int low, int high, int val) {
        while (low <= high) {
            int mid = (low + high) >>> 1;
            if (nums[mid] == val) {
                return mid;
            } else if (nums[mid] < val) {
                low = mid + 1;
            } else {
                high = mid - 1;
            }
        }
        return -1;
    }

    /**
     * 二分查找(非递归)
     *
     * @param nums 有序数组
     * @param val 要查找的值
     * @return 要查找的值在数组中的索引位置
     */
    private static int search(int[] nums, int val) {
        return search(nums, 0, nums.length - 1, val);
    }

    public static void main(String[] args) {
        int[] nums = {1, 2, 5, 7, 8, 9};

        // 非递归查找
        int r1 = search(nums, 7);
        System.out.println(r1);
    }
}

递归实现:

public class BinarySearch {

    private static int searchRecursive(int[] nums, int low, int high, int val) {
        while (low <= high) {
            int mid = (low + high) >>> 1;
            if (nums[mid] == val) {
                return mid;
            } else if (nums[mid] < val) {
                return searchRecursive(nums, mid + 1, high, val);
            } else {
                return searchRecursive(nums, low, mid - 1, val);
            }
        }
        return -1;
    }

    /**
     * 二分查找(递归)
     *
     * @param nums 有序数组
     * @param val 要查找的值
     * @return 要查找的值在数组中的索引位置
     */
    private static int searchRecursive(int[] nums, int val) {
        return searchRecursive(nums, 0, nums.length - 1, val);
    }

    public static void main(String[] args) {
        int[] nums = {1, 2, 5, 7, 8, 9};

        // 递归查找
        int r2 = searchRecursive(nums, 7);
        System.out.println(r2);
    }
}
Java
1
https://gitee.com/fdayu/leetcode.git
git@gitee.com:fdayu/leetcode.git
fdayu
leetcode
leetcode
main

搜索帮助

53164aa7 5694891 3bd8fe86 5694891