二分查找

主要针对的是“有序数组”中查找某个特定元素。

1、二分查找的思想:主要针对的是有序数组,要充分利用数组有序的特性,要是遍历查找,时间复杂度是O(n),就浪费了数组的有序性。其思想就是,每次查找对比的元素都是数组的中间元素,通过比较中间元素和目标元素的大小,进一步的缩小范围,每次比较的范围都缩小为原来的一半。可以用递归的思想来实现。

2、时间空间复杂度:时间复杂度 O(logn),空间复杂度O(1)

3、代码:

递归实现:

int binarysearch(int array[], int low, int high, int target) {
    if (low > high) return -1;
    int mid = low + (high - low) / 2;
    if (array[mid] > target)
        return binarysearch(array, low, mid - 1, target);
    if (array[mid] < target)
        return binarysearch(array, mid + 1, high, target);
    return mid;
}

循环实现:

int bsearchWithoutRecursion(int a[], int key) {
    int low = 0;
    int high = a.length - 1;
    while (low <= high) {
        int mid = low + (high - low) / 2;
        if (a[mid] > key)
            high = mid - 1;
        else if (a[mid] < key)
            low = mid + 1;
        else
            return mid;
    }
    return -1;
}

4、应用

  二分查找也可以用来查找含有重复数字的排序数组的first数字或last数字。

剑指offer:数字在排序数组中出现的次数

    //二分法查找第一个数字
    public static int getFirstNumberIndex(int[] array, int k) {
        int result = -2;
        int start = 0;
        int end = array.length - 1;
        while (start <= end) {
            int mid = (start + end) / 2;

            //若中间数字大于k,在前半部分查找
            if (array[mid] > k) {
                end = mid - 1;
            } else if (array[mid] < k) {
                start = mid + 1;
            } else if (array[mid] == k) {
                //用短路与去判断mid>0,防止ArrayIndexOutOfBoundsException
                if (mid > 0 && array[mid - 1] != k || mid == 0) {
                    result = mid;
                    break;
                } else {
                    end = mid - 1;
                }
            }
        }
        return result;
    }

参考博客:https://www.cnblogs.com/morethink/p/8379475.html

原文地址:https://www.cnblogs.com/guoyu1/p/12058391.html