二分法排序

发布时间:2023-05-20

二分查找(Binary Search)

二分查找(Binary Search),是一种在有序数组中查找某一特定元素的搜索算法。二分查找的思想类似于分治思想。

一、基本思想

实现二分法排序,首先要明确基本思想,即:在有序数组中,每次取数组的中间位置,如果该位置上的值不是要查找的值,继续在大于或者小于它的那一半中查找,直到查找到目标为止。

int binarySearch(int[] arr, int target) {
    int left = 0;
    int right = arr.length - 1;
    while (left <= right) {
        int mid = (left + right) / 2;
        if (arr[mid] == target) {
            return mid;
        } else if (arr[mid] < target) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    return -1; // 没有找到
}

二、时间复杂度

二分法排序的时间复杂度为 O(log n)。因为每次都会将数组缩小一半,在最坏的情况下,需要进行 log n 次操作才能找到目标元素。

三、适用条件

二分法排序仅适用于有序数组。在无序数组中查找元素,需要先将数组排序再进行查找。

四、如何处理重复元素

有时候数组中可能会有重复的元素,怎么办呢? 一种方法是,在查找到目标元素的时候,向前或向后遍历,查找其他相同的元素。这种方法的时间复杂度为 O(k),其中 k 为相同元素的个数,因此效率较低。

int binarySearch(int[] arr, int target) {
    int left = 0;
    int right = arr.length - 1;
    while (left <= right) {
        int mid = (left + right) / 2;
        if (arr[mid] == target) {
            // 查找其他相同的元素
            int i = mid - 1;
            while (i >= 0 && arr[i] == target) { i--; }
            int j = mid + 1;
            while (j < arr.length && arr[j] == target) { j++; }
            return mid;
        } else if (arr[mid] < target) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    return -1; // 没有找到
}

另一种方法是,在进行比较的时候,判断中间值是否包含在目标区间内。

int binarySearch(int[] arr, int target) {
    int left = 0;
    int right = arr.length - 1;
    while (left <= right) {
        int mid = (left + right) / 2;
        if (arr[mid] == target) {
            if (mid == 0 || arr[mid - 1] < target) {
                return mid;
            } else {
                right = mid - 1;
            }
        } else if (arr[mid] < target) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    return -1; // 没有找到
}

五、应用场景

二分法排序最常用的应用场景是在数组中查找元素。除此之外,二分法排序还可以用于一些其他的问题,例如求开方、最大值(最小值)等。