zoukankan      html  css  js  c++  java
  • 算法 *-* 二分查找(三种情况, 统一模板)

    1. 总结

    binary_search:普通的二分搜索,就是搜索target本身的值

    left_bound:搜索比target小的数字的个数。有序数组nums = [2,3,5,7],target = 1,算法会返回 0,含义是:nums中小于 1 的元素有 0 个;nums = [2,3,5,7], target = 8,算法会返回 4,含义是:nums中小于 8 的元素有 4 个。

    right_bound:搜索比target大的数字的个数。有序数组nums = [2,3,5,7],target = 1,算法会返回 4,含义是:nums中大于 1 的元素有 4 个;nums = [2,3,5,7], target = 8,算法会返回 0,含义是:nums中大于 8 的元素有 0 个。

    只要修改两处(注释处)即可变化出三种写法
    int binary_search(int[] nums, int target) {
        int left = 0, right = nums.length - 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) {
                // 直接返回
                return mid;
            }
        }
        // 直接返回
        return -1;
    }
    
    int left_bound(int[] nums, int target) {
        int left = 0, right = nums.length - 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;
            }
        }
        // 最后要检查 left 越界的情况
        if (left >= nums.length || nums[left] != target)
            return -1;
        return left;
    }
    
    
    int right_bound(int[] nums, int target) {
        int left = 0, right = nums.length - 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) {
                // 别返回,锁定右侧边界
                left = mid + 1;
            }
        }
        // 最后要检查 right 越界的情况
        if (right < 0 || nums[right] != target)
            return -1;
        return right;
    }

    2. 易错点

    2.1 防止int溢出

    计算 mid 时需要防止溢出,代码中left + (right - left) / 2就和(left + right) / 2的结果相同,但是有效防止了left和right太大直接相加导致溢出

    2.2 不要出现 else

    不要出现 else,而是把所有情况用 else if 写清楚,这样可以清楚地展现所有细节

    3. 参考文章

    作者:labuladong, 我作了首诗,保你闭着眼睛也能写对二分查找
    公众号:labuladong

  • 相关阅读:
    设计模式之观察者模式
    设计模式之建造者模式
    设计模式之外观模式
    设计模式之模板方法模式
    设计模式之原型模式
    自己动手写计算器v1.1
    自己动手写计算器v1.0
    Guid的使用
    设计模式学习---代理类
    StringBuilder的使用
  • 原文地址:https://www.cnblogs.com/frankcui/p/14182225.html
Copyright © 2011-2022 走看看