美文网首页
二分查找(变体)代码框架

二分查找(变体)代码框架

作者: 木木与呆呆 | 来源:发表于2022-07-18 11:03 被阅读0次

    1.说明

    前面介绍了二分查找代码框架,
    查找的都是与target相同的数,
    本文介绍的二分查找变体,
    查找的是正好大于或者小于target的数,
    即要找的数target不存在,
    希望返回满足一定要求的数。

    2.查找正好大于target的元素

    这是二分查找代码框架中,
    查找左侧边界代码框架的变体,
    当target不存在时,
    得到的索引恰好是比target大的最小元素的索引,
    即nums数组中第1个大于target的元素索引。

    public static int leftBound(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        // 下面的两个判断可省略,最终结果会覆盖这两种情况
        // target比最小的元素还小,那索引为0的元素正好比target大
        if (target < nums[left]) {
            return 0;
        }
        // target比最大的元素还大,则-1表示没有比target大的元素了
        if (target > nums[right]) {
            return -1;
        }
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (nums[mid] < target) {
                left = mid + 1;
            } else if (nums[mid] > target) {
                right = mid - 1;
            } else if (nums[mid] == target) {
                // 不能返回,锁定左边界,继续缩小右边界
                right = mid - 1;
            }
            // 上面的"right = mid - 1;"代码体相同,
            // 判断条件可以合并为else if (nums[mid] >= target)
        }
        return left;
    }
    

    3.查找正好小于target的元素

    这是二分查找代码框架中,
    查找右侧边界代码框架的变体,
    当target不存在时,
    得到的索引恰好是比target小的最大元素的索引,
    即nums数组中最后一个小于target的元素索引。

    public static int rightBound(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        // 下面的两个判断可省略,最终结果会覆盖这两种情况
        // target比最小的元素还小,则-1表示没有比target小的元素了
        if (target < nums[left]) {
            return -1;
        }
        // target比最大的元素还大,那索引为nums.length-1的元素正好比target小
        if (target > nums[right]) {
            return right;
        }
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (nums[mid] < target) {
                left = mid + 1;
            } else if (nums[mid] > target) {
                right = mid - 1;
            } else if (nums[mid] == target) {
                // 不能返回,锁定右边界,继续缩小左边界
                left = mid + 1;
            }
            // 上面的"left = mid + 1;"代码体相同,
            // 判断条件可以合并为else if (nums[mid] <= target)
        }
        return right;
    }
    

    4.二分查找(变体)代码框架优化

    如下代码优化后非常简洁,
    适合在实际项目中使用,
    但是不推荐记忆下面的代码框架,
    因为合并了很多实现细节,
    不利于分析和理解,
    还是推荐记忆上面的原始版本。

    4.1.查找左侧边界变体优化

    public static int leftBoundAdvance(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (nums[mid] < target) {
             left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        return left;
    }
    

    4.2.查找右侧边界变体优化

    public static int rightBoundAdvnce(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (nums[mid] <= target) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        return right;
    }
    

    相关文章

      网友评论

          本文标题:二分查找(变体)代码框架

          本文链接:https://www.haomeiwen.com/subject/zenrirtx.html