学算法,先从二分查找开始吧

总纲

思路很简单,细节是魔鬼。分为三个常用场景:寻找一个数,寻找左侧边界,寻找右侧边界。最后给出力扣上的题目例子。
还可以在GitHub上观看哦。AlgorithmNotes

基础框架

int binarySearch(int[] nums, int target) {
    int left = 0, right = ...;
    
    while(...) {
        int mid = (right + left) / 2;
        if (nums[mid] == target) {
            ...
        } else if (nums[mid] < target) {
            left = ...
        } else if (nums[mid] > target) {
            right = ...
        }
    }
    return ...;
}
  • 把所有情况都写清楚,展示所有细节。
  • mid = left + (right - left) / 2,防止溢出。
  • 三个框架可以合成一个,但适用面很小,不如单独的左区间或右区间使用广。

寻找一个数

int binarySearch(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)
            return mid;
        else if (nums[mid] < target)
            left = mid + 1; 
        else if (nums[mid] > target)
            right = mid - 1; 
    }
    return -1;
}

最基础的二分查找,每次查找都是左闭右闭区间。

  • 循环条件是 <=;
  • 更新是 left=mid+1,right=mid-1。

必要条件是数组内无重复整数。

寻找左侧边界

int left_bound(int[] nums, int target) {
    if (nums.length == 0) return -1;
    int left = 0;
    int right = nums.length;
    
    while (left < right) { 
        int mid = (left + right) / 2;
        if (nums[mid] == target) {
            right = mid;
        } else if (nums[mid] < target) {
            left = mid + 1;
        } else if (nums[mid] > target) {
            right = mid;
        }
    }
    
    return left;//此处返回left,right都可,因为相等
}

每次查找都是左闭右开区间。

  • 循环条件是 left < right;
  • 更新是 left = mid + 1, right = mid,可以理解为下一次搜索区间是 [left,mid), [mid+1,right)
  • 每次找到target时,因为存在重复数字且要找的是左边界,所以不断向左收缩, right = mid。

寻找右侧边界

int right_bound(int[] nums, int target) {
    if (nums.length == 0) return -1;
    int left = 0, right = nums.length;
    
    while (left < right) {
        int mid = (left + right) / 2;
        if (nums[mid] == target) {
            left = mid + 1; 
        } else if (nums[mid] < target) {
            left = mid + 1;
        } else if (nums[mid] > target) {
            right = mid;
        }
    }
    
    return left - 1; 
}
  • 循环条件是 left < right;
  • 更新是 left = mid + 1, right = mid,可以理解为下一次搜索区间是 [left,mid), [mid+1,right);
  • 每次找到target时,因为存在重复数字且要找的是右边界,所以不断向右收缩, left = mid + 1;
  • 返回 left - 1,因为更新时 left = mid + 1,所以循环结束时 nums[left-1] 才是target。

题目

题号题目链接
704二分查找(打板题)105265723
33搜索旋转排序数组105265887
35搜索插入位置(打板题)105265922
153寻找旋转排序数组中的最小值105265935
154寻找旋转排序数组中的最小值II105265998
162寻找峰值105266055
275H指数II105266073
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值