1月5日学习——二分再辨析

自己的碎碎念(不用看)

朴素二分查找,在我自己目前看过的书中都只是简略的写过,而且大多数只有果没有因(当然肯定是我自己不聪明的成分),所以我一直想花时间把二分查找弄明白。
一直以来都是很搞不懂,为什么一个简单的大于号小于号就能决定查找的方向呢。这次我花了时间看了B站上一个名叫skywave的up主的视频搞明白了

主题部分

int bs(int *a , int l , int r , int target){
  //第一个大于target出现的位置
  while(l <= r){
  	int mid = (l + r)>>1;
  	if(a[mid] > target){
  		r = mid - 1;
  	}else{
  		l = mid + 1;
  	}
  }
  return l;
  //最后一个小于等于target的位置 return r
}
  • 下面我来仔细说这段代码,如果我们要找的是第一个大于target的位置,把 l , r l,r l,r都看作两个指针
  • 在满足 r r r指针所指向的值大于 t a r g e t target target的时候, r r r指针就会不断地向着 l l l指针的方向靠拢
  • 直到 r r r指针下一次移动到的方向不满足 > t a r g e t >target >target这个条件了
  • 那么此时 a [ r ] < = t a r g e t a[r]<=target a[r]<=target那么下一步就执行else语句
  • l l l指针不断向 r r r指针靠拢,直到相遇
  • 因为相遇之后还不满足条件,所以继续执行else语句
  • 然后这个时候 l l l指针超越了 r r r指针,因为 r r r指针指向的是最后一个小于等于 t a r g e t target target的位置,且 l l l指针比 r r r指针多了一位,那么此时一定是 l l l所指的元素位置一定是第一个大于 t a r g e t target target的位置,即 a [ l ] > t a r g e t a[l]>target a[l]>target;
int bss(int *a , int l , int r ,int target){
   //最后一个小于target出现的位置
   while(l <= r){
   	int mid = (l + r)>>1;
   	if(a[mid] >= target){
   		r = mid - 1;
   	}else{
   		l = mid + 1;
   	}
   }
   return r;
   //第一个大于等于target的位置就return l
}
  • 如果我们要找的是最后一个小于 t a r g e t target target出现的位置呢?
  • 根据两个指针的特性相比,在中间值一直大于目标值的情况下,我们的最右端指针一直不断向左👈移动,直到他下一个指向的元素不满足这个条件
  • 也就是说此时 r r r指针已经指向了一个小于 t a r g e t target target的元素的位置
  • 以此类推, l l l指针不断接近 r r r指针并最后超过 r r r指针一个位置成为一个指向第一个大于等于 t a r g e t target target的值的位置
    ** l l l永远指向的是一个符合条件的位置,而 r r r永远指向一个非法的位置,也就是跟着他反着来,这才有了为什么大于小于决定了这个二分查找的方向。

——写于1月5日 23:41

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Dou_Huanmin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值