Leetcode刷题-704:二分查找

解题思路

  • 1.题目描述
  • 2.题目分析
  • 3.题目解答
    • 3.1 左闭右闭区间
    • 3.2 左闭右开区间

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

总结:区间控制要严格

你可能感兴趣的:(leetcode刷题记录,leetcode)