Leetcode刷题-704:二分查找

1.题目描述

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
示例1:

输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4

示例2:

输入: nums = [-1,0,3,5,9,12], target = 2
输出: -1
解释: 2 不存在 nums 中因此返回 -1

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/binary-search

2.题目分析

二分查找的过程说到底就是一个区间的变化的过程,思想描述起来是很简单的,就是在一个已经排好序的序列中查找的时候每次都会通过判断target值应该在待查找序列的左半边还是右边来进行区间筛选之后再查找。

但是在具体实现编码的时候区间的变化过程确实会比较容易搞混,这个时候就要注意把握我们所设置的边界条件,也就是leftright之间的关系,它们之间的<或者<=应该是持续不变的。我们下面对两种情况分开讨论:

  • 首先如果我们定义的条件是left<right,也就是我们工作的区间是[left,right)那么在target与中间值比较之后,我们更新区间就应该是
    • target>Nmidleft = mid+1
    • target<Nmidright=mid-1
  • 如果定义的条件是left<=right,也就是我们工作的区间是[left,right]。那么就是如下的情况:
    • target>Nmidleft = mid+1
    • target<Nmidright = mid

为什么不同的边界条件下更新的区间不同呢?而且是只有right的边界值更新才有区别呢?我们仔细观察其边界条件,会发现经过这样的边界变化,变化前后left和right构成的查值区间分别是[left,right][left,right)。没错,虽然它们的表达形式不一样,但是其区间内的值是一样的。所以不论我们是选择二者哪一种边界条件,只要我们把握这个不变量——区间内的可查找值,那就可以完成二分查找的过程,但是注意不能混用,如果在一种区间下使用了另一种区间下的边界更新,那就可能会导致死循环。

3.题目解答

3.1 左闭右闭区间

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left =0,right=nums.size()-1;
        while(left<=right){
            int mid = left+(right-left)/2;
            if(target<nums[mid]){   
                right = mid-1;
            }
            else if(target>nums[mid]){
                left = mid+1;
            }
            else return mid;
        }
        return -1;
    }
};

3.2 左闭右开区间

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left =0,right=nums.size();
        while(left<right){
            int mid = left+(right-left)/2;
            if(target<nums[mid]){   
                right = mid;
            }
            else if(target>nums[mid]){
                left = mid+1;
            }
            else return mid;
        }
        return -1;
    }
};

总结:区间控制要严格

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值