5-1 二分查找法

来源:互联网 发布:文爱都用什么软件 编辑:程序博客网 时间:2024/06/07 23:17

我们使用数据结构的核心是为了解决问题。使用的数据结构可以高效地解决一类问题。而不是为了使用数据结构而使用数据结构。

查找问题是计算机中非常重要的一类基础的问题。

使用二分查找法的前提

对于有序的数列才能使用二分查找法。

小故事

二分查找法的思想在 1946 年就被提出来了。但是第 1 个没有 bug 的二分查找法在 1962 年才出现。

二分查找法的时间复杂度是 O(logn) 。

注意二分查找法有一个坑:查找中间数。

二分查找法的循环实现:

public class BinarySearch {    /**     * 首先要求带查找的数组应该是排好序的     *     * @param arr     * @return     */    public static int search(int[] arr, int target) {        SortTestHelper.testSorted(arr);        int l = 0;        int r = arr.length - 1;        // arr[0,r]        while (l <= r) {            // int mid = (l + r) / 2;            int mid = l + (r - l) / 2;            if (arr[mid] == target) {                return mid;            }            if (target < arr[mid]) {                // 回到定义中就好理解了                r = mid - 1;            } else {                l = mid + 1;            }        }        return -1;    }    public static void main(String[] args) {        int[] arr = {1, 3, 5, 6, 8, 9, 13, 16, 17, 24, 56, 78};        int search = search(arr, 17);        System.out.println(search);    }}

二分查找算法的递归实现:

public class BinarySearch2 {    /**     * 首先要求带查找的数组应该是排好序的     *     * @param arr    待查找的已经排好序的数组     * @param target 待查找的数     * @param left   左边界,可以取到     * @param right  右边界,可以取到     * @return     */    public static int binarySearch(int[] arr, int target, int left, int right) {        // 注意:这里是小于等于号,只要是区间中至少有一个元素都要递归下去        // 隐含了递归到底的情况        if (left <= right) {            int mid = left + (right - left) / 2;            if (arr[mid] == target) {                return mid;            } else if (target < arr[mid]) {                return binarySearch(arr, target, left, mid - 1);            } else if (target > arr[mid]) {                return binarySearch(arr, target, mid + 1, right);            }        }        return -1;    }    public static void main(String[] args) {        int[] arr = {1, 3, 5, 6, 8, 9, 13, 16, 17, 24, 56, 78};        int search = binarySearch(arr, 17, 0, arr.length - 1);        System.out.println(search);    }}

编写递归的注意事项:

1、判断递归到底的情况;

2、注意下面的这个代码片段

else if (target < arr[mid]) {    return binarySearch(arr, target, left, mid - 1);} else if (target > arr[mid]) {    return binarySearch(arr, target, mid + 1, right);}

一定要写 return 语句,要不然总是返回 -1。

可以使用递归的方式实现二分查找法。

递归的思维是很容易的。

1、递归实现通常思维起来更容易;

2、递归在性能上会略差。

todo

试着实现二分查找法的变种:floor、ceil 函数。在白板编程的前提下写出来。

之前假设在待查找数组中是没有重复。

floor 地板函数和 ceil 天花板函数是这样定义的:

1、在有很多 target 相同元素的数组中,floor 返回第1个出现 target 的元素的索引,ceil 返回最后一个出现这个元素的索引;

2、在没有 target 元素的数组中,floor 返回的是最后一个比 target 小的元素的索引,ceil 返回的是第 1 个比 target 大的元素的索引。

试着在白板编程的情况下将这个函数实现出来,加油!

原创粉丝点击