第 4 章 居合斩!二分查找

本文为个人刷题记录
发现了自己多久没搞懂的一个东西:
我发现那些l<r的题,,r的缩减范围都是 r = mid,
l<=r的话,r的范围就变成了r = mid - 1

2021/9/15心得 详见 162. 寻找峰值
至于到底是while(l <= r) 还是 while(l < r )要看实际情况。这题中,nums[ mid ] < nums[mid + 1]说明mid值不可用,mid需要比两边都大。但是nums[mid] >= nums[mid + 1]说明mid是可以用的,只是不确定mid左边是否还有更高值。需要保留到下一轮,此时r = mid。由此while(l < r)。否则就需要边界判断

69. x 的平方根

朴素遍历必超时。别想了。。
但是二分也是不能用i*i 这种会炸的操作。所以乘法要转换成除法。
对于每一个mid值,x / mid = sqrt,如果这个mid就是x开方,那么mid == sqrt。当然也有开不尽的时候,此时l = = r,返回r就好。
如果mid > sqrt ,说明mid过大了,缩减r的范围mid - 1。反之增大l为mid +1。

34. 在排序数组中查找元素的第一个和最后一个位置
首先判空条件,nums是空,或者找到的lower位置是nums.size()或者Nums[lower]根本就不是target。这些均返回{-1,-1};
关于一个 lower_bound函数和 upper_bound函数。
lower_bound中是找最小位置的target,所以在右边界判断时,哪怕是nums[mid]等于target也要缩小r的范围,但是在upper_bound中,就不需要。但是,最后的upper值需要-1,因为在函数中找到的并不是等于target的值,而是target后一个。

81. 搜索旋转排序数组 II
这道题绝绝子!!!
(1)无法使用 l<r作为循环判断条件。因为满足条件返回true在循环内,循环以外都是false。如果写成l<r,有可能数组只有一个数,无法进入循环直接返回外层false;
(2)这题需要先二分判断递增在哪一个部分,再在递增区间二分寻找target。
首先第一次二分的判断:if(nums[start] == nums[mid])这种情况下无法判断,因为如果中点和左端的数字相同,我们并不能确定是左区间全部相同,还是右区间完全相同。在这种情况下,我们可以简单地将左端点右移一位,然后继续进行二分查找。
(3)判断出mid右侧递增。此时只能判断target是否大于等于nums[mid],且target不能超出右边界nums[end],因为右边递增需要把target置于右侧才可二分。。左递增同样如此。

154. 寻找旋转排序数组中的最小值 II
把81搞懂了这道题就会写了,舒服。
这里还是要判断他的递增区间在哪
(1)nums[mid] < nums[r] 说明mid的右边都是递增(本来就是右递增,表名这一部分没有变),那么最小值肯定在mid的左边,反之取右边
(2)但是nums[mid] == nums[r]时是无法判断的,这是r–,反之nums[r]与nums[mid]相等,少一个也不会影响结果判断。

540. 有序数组中的单一元素
方向对了思路错了,确实要分四种方式判断。但是判断mid的时,找到与Nums[mid]相等的值需要把另一个相等的也缩减范围。
(1)mid 与 mid+1相等
① mid+1的右边还有奇数个
说明要找答案在mid+1的右边,l = mid+2(要把mid和mid+1一起缩减)
② mid左边还有奇数个
要找的答案在mid的左边 r = mid-1;
(2)mid与mid - 1相等
①mid-1左边有奇数个
答案在mid - 1的左边r = mid - 2;
② mid的右边有奇数个
答案在mid 的右边,l = mid + 1
(3)不相等,好家伙就你了 return nums[mid]
最后返回nums[l]

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值