二分查找

简介: 二分查找

二分查找的前提


网络异常,图片无法展示
|


使用递归实现二分查找


public static <E extends Comparable<E>> int search(E[] arr, E target) {
        return search(arr, 0, arr.length - 1, target);
    }
    private static <E extends Comparable<E>> int search(E[] arr, int l, int r, E target) {
        if(l > r) {
            return -1;
        }
        int mid = l + (r - l) / 2;
        if(arr[mid].compareTo(target) == 0) { // 刚好找到中间的位置
            return mid;
        }else if (arr[mid].compareTo(target) > 0) { // 查找mid前面的元素
            return search(arr, l, mid - 1, target);
        }else { //(arr[mid].compareTo(target) < 0)
            return search(arr, mid + 1, r, target);
        }
    }


使用非递归实现二分查找


private static <E extends Comparable<E>> int search1(E[] arr, E target) {
        int l = 0, r = arr.length - 1;
        while(l <= r) { // 数组中存在元素时
            int mid = l + ( r - l) / 2;
            if(arr[mid].compareTo(target) == 0) { // 刚好中间的元素就是
                return mid;
            }
            if(arr[mid].compareTo(target) > 0) { // 中间的元素小于target,接着查找右边的列表
                r = mid - 1;
            }else { // 中间的元素大于target, 接着查找左边的列表
                l = mid + 1;
            }
        }
        return -1;
    }


二分查找法的变种


查找大于target的最小值


  • 当未查找到这样的元素,那么将返回数组长度。


  • 当中间值大于等于目标值,那么查询返回下一边界需要加上上一次的中间值,所以r = mid


网络异常,图片无法展示
|


/**
 * 查找大于target的最小值
 * @param arr
 * @param target
 */
public static <E extends Comparable<E>> int upper(E[] arr, E target) {
    int l = 0, r = arr.length;
    while(l < r) {
        int mid = l + (r - l) / 2;
        if(arr[mid].compareTo(target) == 0) {
            return mid + 1;
        }else if(arr[mid].compareTo(target) > 0) { // 这个r = mid是因为mid的位置可能是目标值
            r = mid;
        }else {
            l = mid + 1;
        }
    }
    // l和r最后都都指向同一个位置。没找到则返回arr.length
    return l;
}


查找目标元素最大的下标元素 ceil


  • 如果有等于target的元素就返回最大的下标元素。


  • 如果没有等于target的元素,那么就返回大于target的最小元素。即上面实现的upper函数。


网络异常,图片无法展示
|


public static <E extends Comparable<E>> int ceil(E[] arr, E target) {
        int index = upper(arr, target);
        if(arr[index - 1].compareTo(target) == 0) {
            return index - 1;
        }
        return index;
    }


查找目标元素最小的小标元素 lower_ceil


  • 如果有等于target的元素就返回最小的下标元素。


  • 如果没有等于target的元素,那么就返回大于target的最小元素。即上面实现的upper函数。


网络异常,图片无法展示
|


查找小于target的最大值


网络异常,图片无法展示
|


按照上面的逻辑写成的程序会出现死循环


网络异常,图片无法展示
|


网络异常,图片无法展示
|


LeetCode相关习题


LeetCode 875


网络异常,图片无法展示
|


/**
     * 使用二分法,解决leetCode875
     * @param piles
     * @return
     */
    public static int leetCode875(int[] piles, int h) {
        // 假设他先吃二分法中间的那个根数
        int l = 1; // 最少吃一根
        int r = Arrays.stream(piles).max().getAsInt(); // 假设吃数组中最大数量的根数
        while(l < r) {
            int mid = l + (r - l) / 2;
            if(eatingTime(piles, mid) <= h) { // 此时mid可能会目标值
                r = mid;
            }else {
                l = mid + 1;
            }
        }
        return l;
    }
    public static int eatingTime(int[] arr, int k) {
        int res = 0;
        for(int pile: arr) {
            res = res + pile / k + (pile % k > 0 ? 1 : 0);
        }
        return res;
    }


LeetCode 1011


网络异常,图片无法展示
|


相关文章
|
算法 索引
二分查找(详解)
二分查找(详解)
|
7月前
|
算法 索引
二分查找(一)
二分查找(一)
|
7月前
|
算法 索引
二分查找(二)
二分查找(二)
|
7月前
|
算法 C++
C++021-C++二分查找
C++021-C++二分查找
C++021-C++二分查找
|
算法 C语言
这就是二分查找?
本文通过简单的猜数字小游戏向大家介绍二分查找的基本原理。
126 2
|
算法 索引
【二分查找】
【二分查找】
|
存储 算法
6-2 二分查找
6-2 二分查找
174 0