Leetcode第35题:搜索插入位置,二分查找实现

搜索插入位置Leetcodehttps://leetcode.cn/problems/search-insert-position/

题目粘贴:

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

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

示例1:

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

 示例2:

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

示例3:

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

 

 

题目分析:

题中告诉我们数组是有序的,并且要求时间复杂度不超过O(log n),所以我使用二分查找来完成。找到目标值较为简单,本题中,由于目标值未必存在,所以如果目标值不存在,我们就要返回适合它插入的位置(数组是有序的)。我们重点来看一下如何找到正确的插入位置

 

代码:

class Solution {
    public int searchInsert(int[] nums, int target) {
        int l=0,r=nums.length-1;
        while(l<=r)
        {
            int mid=(l+r)/2;
            if(nums[mid]==target)
            {
                return mid;//如果找到目标值,就返回
            }else if(nums[mid]<target)//如果目标值在mid的右边
            {
                l=mid+1;
            }else//如果目标值在mid左边
            {
                r=mid-1;
            }
        }
        return l;//如果没有找到目标值,就返回L,当作要插入的位置
    }
}

解题思路:

先看上面的代码,很多朋友可能不理解,为什么L始终为要插入的地方。

先看我们的循环条件:while(l<=r)。也就是说:如果没找到目标值,L指向的位置一定是大于R的,对不对?

要想L>R,又分为两种情况:

1.R移到了L的左边,在二分查找中,当目标值小于mid的时候,R才需要左移。

2.L移到了R的右边,同上,目标值大于mid的时候,L才需要移动,并且是右移。

也就是说:当没有找到目标值的时候,循环结束,L一定是在R的右边,L=R+1;

接下来我将给出推理过程,不管是情况1结束循环还是情况2结束循环,目标值的插入位置都为L;

 

情况1:R移到了L的左边

假设此时以下面这个存储五个元素的数组arr为例,我们将所要寻找的目标值target设为6。

L,mid,R分别为:left,middle,right的缩写,区间为左闭右闭;

L和R的初始值分别指向0和arr.length-1,此时寻找的范围为[0,4];

09abd955a18a483d97f04b9151fcfdb4.png 

计算mid的值为:mid=(L+R)/2=(0+4)/2=2;

因为arr[mid]=arr[2]=5<6的值,所以mid以及mid左边的值可以不考虑了

缩小要查找的范围,往mid右边找,L=mid+1=3;如下图:

3b93b6c654f04bf6b789e36f4ab3957f.png

此时要查找到范围为[3,4],mid=(L+R)/2=(3+4)/2=3;mid和L指向同一位置。

重点:

因为,arr[3]=7>6,此时arr[3]上的值大于target,所以接下来应该往左找

R=mid-1=3-1=2;此时范围如下图:R移至L的左边,不满足循环条件,循环结束。

此时L指向的位置就是目标值应该插入的位置。

dc6b0107428a415d81c8304e18416776.png

 

 

情况2:L移到了R的右边

3bd5b1d5d3df460aa8d85963d424b27f.png

还是这个数组,只不过这次我们将目标值target的值改为:4

计算mid的值为:mid=(L+R)/2=(0+4)/2=2;

 

 

310026646cb64e539f423e1e439591a6.png

arr[2]=5>4,所以接下来应该往左找,缩小范围,将R指向mid减一。

mid=(L+R)/2=(0+1)/2=0;此时mid和L指向同一位置。

arr[mid]=1<4,所以往右找,移动L的位置,L=mid+1=1

d6da9b3a946047998243d9d94b61f15e.png

此时L和R指向同一个位置,但是我们的循环条件是L<=R,此时仍然满足循环条件,并且也没有找到目标值。所以循环继续,mid=(L+R)/2=1;如上图,此时L,M,R指向同一处。arr[m]=3<4

所以L还要往右边移动,L=mid+1=2;如下图:

60e00283b3914f9582484f74a362bf7d.png

此时L指向索引为2,R指向索引1。所以L>R不满足循环条件,跳出循环,此时目标值应插入的位置依然为L所指;所以,如果没找到目标值,循环结束后,不管什么样的情况,L一定在R右边并且等于R+1;

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值