[算法][深入讨论] 更透彻地理解二分法

二分虽简单,细节很难改。研究不深入,用时两行泪。

你知道吗?在所有懂二分法的人中,只有8%的人能够完全掌握二分法

上升序

贴入模板(上升序)(its表示要找的数),最终可以使用 left 当做寻找到的数:

1         int left = 0,right = n - 1;
2         int mid;
3         while(left != right){
4             mid = (left + right) / 2;
5             if(its <= SortedList[mid]) right = mid;
6             else left = mid + 1;
7         }

二分法必然会碰到 left + 1 == right 的情况,此时 mid == left,在这种情况将时讨论:

  • 若its刚好不在SortedList中,此时一定有 SortedList(left) == SortedList(mid) < its < SortedList(right),那么必定向右缩进(改变left保留right)使 left = mid +1 == right,即最终寻找的是第一个比list大的数

 

  • 若只有一个its在Sortedlist中,那么此时一定有 SortedList(left) == its 或者 SortedList(right) == its,但是无论哪一种情况,都会使 left== right == SortedList-1(its)      (-1次表示反函数),即最终寻找的是那个唯一等于its的数

 

  • 若有多个its在Sortedlist中,那么此时一定有 SortedList(left) == SoredList(right) == its,此时寻找的一定是List中等于its,但是我们想要知道寻找的是第几个等于its的数。若已经达到SortedList(left) == SoredList(right) == its的情况,此时一定是往左缩进(改变right = mid,保留left),即最终变化是寻找的是当前第一个等于its的数。由于每次在等于的情况都会向左缩进,所以在多个its在Sortedlist中,必定寻找的是第一个等于its的数

所以该算法求的是 从左到右第一个大于或者等于its的数

 

 

下降序

关于下降序就是把代码第5行的 <= 改为 >=

那么同理,该算法求的是 从左到右第一个小于或者等于its的数

 

 

总结

整体来看,该二分法是在不包含its是偏右方(第一个大于/第一个小于),在包含its中是偏左方(第一个等于)

以下括号内为下降序,括号外是上升序

若序列就是要找 第一个比its大于(小于)或者 等于 的数,那么直接套用SortedList(left)即可

若想要找到 第一个比its大于(小于) 的数,那么可以加一条 while(SortedList(left) != its) left++

若想要找到 最后一个比 its 小于(大于) 的数,只需要 left - 1 即可

若想要找到 最后一个比its小于(大于) 或者 等于 的数,那么加一条while(SortedList(left) != its) left++ 后再让 left - 1 即可。

 

posted @ 2022-01-05 15:14  蒟蒻zExNocs  阅读(49)  评论(0)    收藏  举报