二分搜索算法总结

二分搜索算法总结算法框架二分查找并不简单,Knuth 大佬(发明 KMP 算法的那位)都说二分查找:思路很简单,细节是魔鬼。很多人喜欢拿整型溢出的 bug 说事儿,但是二分查找真正的坑根本就不是那个细节问题,而是在于到底要给 mid 加一还是减一,while 里到底用 <= 还是 <。二分查找根据搜索区间分类有两种情况:「搜索区间」是 [left, right] :​ right = nums.length - 1​ while (left <= right)​ left
摘要由CSDN通过智能技术生成

二分搜索算法总结

算法框架

二分查找并不简单,Knuth 大佬(发明 KMP 算法的那位)都说二分查找:思路很简单,细节是魔鬼。很多人喜欢拿整型溢出的 bug 说事儿,但是二分查找真正的坑根本就不是那个细节问题,而是在于到底要给 mid 加一还是减一,while 里到底用 <= 还是 <

二分查找根据搜索区间分类有两种情况:

  1. 「搜索区间」是 [left, right] :

​ right = nums.length - 1

while (left <= right)

​ left = mid+1 和 right = mid-1

  1. 「搜索区间」是 [left, right)

​ right = nums.length

while (left < right)

​ left = mid+1 和 right = mid

二分查找根据搜索目的分类有三种情况:

  1. 找到一个 target 的索引

​ 当 nums[mid] == target 时可以立即返回

  1. 找到 target 的最左侧索引

​ 当 nums[mid] == target 时不要立即返回 而要收紧右侧边界以锁定左侧边界

  1. 找到 target 的最右侧索引

​ 当 nums[mid] == target 时不要立即返回 而要收紧左侧边界以锁定右侧边界

🤣当搜索区间是闭区间时,在寻找边界的时候,由于返回条件是left = mid+1 和 right = mid-1 ,可能会在特殊的输入值下出现数组越界的情况,需要排除。

例如下图:
在这里插入图片描述
在这里插入图片描述

算法模板:

注意左右边界收缩时的判断条件;

算法一直使用左闭右闭区间,所以左右区间收缩时要+1或者-1;

寻找左右区间的时候由于终止循环不再是left>right或者==target

而是只有left>right

所以需要在返回时进行判断。

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;
        }
    }
    // 最后要检查 
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值