84.算法 - 二分法查找

二分查找的核心思想理解起来非常简单,有点类似分治思想。即每次都通过跟区间中的中间元素对比,将待查找的区间缩小为一半,直到找到要查找的元素,或者区间被缩小为 0,时间复杂度为O(logn)。

二分查找虽然性能比较优秀,但应用场景也比较有限:
1.底层必须依赖数组,主要原因是二分查找算法需要按照下标随机访问元素。
2.还要求数据是有序的,如果数据没有序,我们需要先排序。所以,如果我们针对的是一组静态的数据,没有频繁地插入、删除,我们可以进行一次排序,多次二分查找。这样排序的成本可被均摊,二分查找的边际成本就会比较低。但是,如果我们的数据集合有频繁的插入和删除操作,要想用二分查找,要么每次插入、删除操作之后保证数据仍然有序,要么在每次二分查找之前都先进行排序。针对这种动态数据集合,无论哪种方法,维护有序的成本都是很高的。

public class BinarySearch {
    public static void main(String[] args) {
        int[] arr = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9};
        int target = arr[new Random().nextInt(arr.length)];
        int index = find(arr, target);
        System.out.println(target + " " + index);
    }
 
    /**
     * 在有序数组arr中,查找target
     * 如果找到target,返回相应的索引index
     * 如果没有找到target,返回-1
     */
    private static int find(int[] arr, int target) {
        return find(arr, target, 0, arr.length - 1);
    }

    private static int find(int[] arr, int target, int l, int r) {
        if (l > r) return -1;
        // int mid = (l+r)/2;
        // 防止极端情况下的整形溢出,使用下面的逻辑求出mid
        int mid = l + (r - l) / 2;
        if (target > arr[mid]) {// target在mid右侧
            return find(arr, target, mid + 1, r);
        } else if (target < arr[mid]) {// target在mid左侧
            return find(arr, target, l, mid - 1);
        } else {
            return mid;
        }
    }
}

你可能感兴趣的:(算法)