二分查找

71 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第6天,点击查看活动详情

二分查找

什么是二分查找呢?

二分查找又叫折半查找,每次查找之后都能去掉一半的数据。二分查找的前提是查找的数据必须有序的。二分查找的时间效率非常高,对于数据量为n的有序序列,时间复杂度为O(log(n))

力扣35题:搜索插入位置

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

请必须使用时间复杂度为 O(log n) 的算法。

示例 1: 输入: nums = [1,3,5,6], target = 5 输出: 2

示例 2: 输入: nums = [1,3,5,6], target = 2 输出: 1

示例 3: 输入: nums = [1,3,5,6], target = 7 输出: 4

思路:首先题目明确要求时间复杂度为O(long(n)),然后发现数组是有序,显然就是要用二分查找。

怎么二分查找?

二分查找要在区间[left,right](区间左右边界可以相等)中确定中间值的下标mid,通过这个mid对应的中间值和目标值target进行比较。

有三种比较结果

1.中间值小于目标值——nums[mid]<target 说明targetmid右边,下次查找是的区间就变成[mid+1,right]

2.中间值大于目标值——nums[mid]>target 说明targetmid左边,下次查找是的区间就变成[left,mid-1]

3.中间值大于目标值——nums[mid]==target 说明找到了,直接返回下标mid

当我们把整个数组查找完的时候,都没有查找到target,就说明要返回target插入的位置.target插入的位置无非就这3种情况.

可以把这个3种情况一起解决吗? 当查找不到的时候,说明区间已经不存在了,即left大于right,那么left就是target应该插入的地方.

为什么呢?

查找不到前的最后一个区间必是left==right,前面我说的是区间的左右边界是可以相等的.

那么模拟最后一步:mid还是为left,假如target大于nums[mid],那么应该插入mid的右边1位,而此时left就是mid+1;小于的情况,就不用我明说了吧;没有等于的情况哈,因为前提就是不存在.

完整代码

class Solution {
public:
  int searchInsert(vector<int>& nums, int target) {
    int left=0;//左边界
    int right=nums.size()-1;//右边界
    while(left<=right)//区间要存在
    {
        int mid=(left+right)/2;//中间位置
        //3种比较结果
        if(nums[mid]<target)
            left=mid+1;
        else if(nums[mid]>target)
            right=mid-1;
        else
            return mid;
    }
    //没有查找到,返回插入的位置
    return left;
  }
};