動機
整理一下
1. [first, last)
左右 * 閉開 => 4種
假設長度為4的array,範圍如下
- 0 <= x < 4
- 0 <= x <= 3
- -1 < x <= 3
- -1 < x < 4
如果bsearch到最後,左右兩邊重合
- 0 <= x < 0
- 0 <= x <= -1
- -1 < x <= -1
- -1 < x < 0
所以我們還是選第一種左閉右開
因此,終止條件是
while i < j:
pass
2. mid = first + (last - first) // 2
原本算中點是(last + first)//2
,但是有可能會加到溢位!!
改成用起點再加上多的部分
記得,中點就是往開去算,故如果變成右閉左開要用
last - (last-first)//2
去算
另外注意,這裡是無條件捨去,另外有無條件進位的中點算法,但我還不知道使用上要怎麼選擇,但有遇過因此被婊的時候
3. first = mid + 1, last = mid
參考文中是用歸納法(那個loop invariant與我印象中的loop invariant不一樣,所以先叫他歸納法)去證為什麼是first = mid + 1, last = mid
但這裡用終止條件的來看,為什麼是first = mid + 1, last = mid
我們的終止條件左閉右開,所以之後的first與last都要左閉右開
因為mid看過了不用保留所以first = mid + 1
,那last呢?
右邊是開,所以last = mid
等到了搜尋完成,最後的結果會是last == first
,所以在最後last的值會連同first被保留,十分有趣。
總結
再一次,去看參考的文章,必看阿!!!
def lower_bound(array, first, last, value):
# 求非降序范围[first, last)内第一个不小于value的值的位置
while first < last: # 搜索区间[first, last)不为空
mid = first + (last - first) // 2 # 防溢出
if array[mid] < value:
first = mid + 1
else:
last = mid
return first # last也行,因为[first, last)为空的时候它们重合