倍增搜尋_形式化分析
本文給出整數集上倍增搜尋的常見形式, 正確性證明和時間複雜度分析..
一: 演算法ForeardDoubleSearch(l, r, p)//正向倍增
如不做特殊說明, 下面的敘述中約定: 序列, 定義函式p(x), 滿足, 存在正整數k, 使得當時p(x) = true,當時p(x) = false
- ForwardDoubleSearch(l, r, p)//初始引數l = 1, r = n, p為判定函式,
- begin = l, len = 2
- while len >= 2
- if p(begin + len - 1)
- begin = begin + len - 1,
- else
- len =
- return begin
對於上述演算法有下述重要結論成立,
(1): 如果對任意, 均有p() = 0, 那麼第3至7行迴圈結束時l = r = 1, 否則第3至7行迴圈經過O(lg(k))次迭代後終止, 且終止時begin = k, 下面給出後邊這一結論的證明.
首先指出, 在任何時刻len的值均為2的整數次冪, 先證明迴圈一定會終止, 且終止時begin = k, 根據第3至7行的程式碼邏輯易知經過有限次(具體是O(lg(k))次)迭代後第四行if語句的判定的條件不成立, ,在此之前的每次迭代中該判定條件均成立, 記次判定條件第一次不成立對應第q次第4行if條件判斷, 此時如果begin = k, 那麼很顯然接下來每次第四行if條件判斷的結果均為false, 經過O(lg(k))次迴圈len減小至1, 迴圈終止且begin = k. 如果第q次第4行if條件判斷時begin
迴圈不變式: 每次第3行迴圈頭檢測之前滿足p(begin + 2 * len - 1)為false
顯然對於第q + 1次迴圈頭檢測上述迴圈不變式成立, 使用數學歸納法易證對於第q + 1次迴圈頭檢測之後的每次迴圈頭檢測上述不變式均成立, 下面給出基於此迴圈不變式的一個重要推論:
推論1: 在第q + 1次迴圈頭檢測之後, 將每連續4次迴圈頭檢測, 分別記為第s, s + 1, s + 2, s + 3, s + 4, s + 5次, 相應的迴圈頭檢測對應的len值分別記為, 滿足或或 或或, 下面給出此推論的證明.
如果第s次迴圈頭檢測之前p(begin + len - 1)為false, 那麼第s次迴圈中執行len = len / 2, 從而
如果第s次迴圈頭檢測之前滿足p(begin + len - 1)成立, 即=記此時begin的值為B, len的值為L, 根據第s次迴圈頭檢測之前p(begin + 2 * len - 1)為false也即p(B + 2 * L - 1)為false, 且第s次迴圈過程中執行語句begin = begin + len - 1, len = len * 2, 那麼第s + 1次迴圈頭檢測之前有len = 2 * L, p(begin + L)為false, 故在第s + 1次迴圈中執行len = len / 2, 在接下來的第s + 2次迴圈頭檢測之前有len = L, 同第s + 1次迴圈頭檢測之前一樣begin + L也即begin + len為false, 對於第s + 2次迴圈頭檢測兩種情況考察
(i)如果在第s + 2次迴圈中p(begin + len - 1)成立, 那麼必有begin + len - 1是使得p為真的最大值, 此輪迴圈執行begin = begin + len - 1, len = len * 2 =2 * L, 在接下來的第s + 3, s + 4次迴圈中均執行len = len / 2, 故在第s + 5次迴圈頭檢測之前
, 從而.
(ii)(i)如果在第s + 2次迴圈中p(begin + len - 1)不成立, 那麼在第s + 2次迴圈中執行len = len / 2, 故在第s + 3次迴圈頭檢測之前len = , 從而
綜上述, 推論1得證.
根據之前給出的迴圈不變式和推論1很容易證明第3至7行迴圈經過O(lg(k))次迭代後終止, 且終止時begin = k, 具體證明過程不再贅述.
一: 演算法ReverseDoubleSearch(l, r, p)//反向倍增
如不做特殊說明, 下面的敘述中約定: 序列, 定義函式p(x), 滿足, 存在正整數k, 使得當時p(x) = false,當時p(x) = true
- ReverseDoubleSearch(l, r, p)//初始引數l = 1, r = n, p為判定函式,
- begin = r, len = 2
- while len >= 2
- if p(begin - len + 1)
- begin = begin - len + 1,
- else
- len =
- return begin
對於上述演算法有下述重要結論成立,
(1): 如果對任意, 均有p() = 0, 那麼第3至7行迴圈結束時l = r = n, 否則第3至7行迴圈經過O(lg(k))次迭代後終止, 且終止時begin = k, 後者的證明可直接類比對於演算法ForeardDoubleSearch(l, r, p)的分析過程, 此處不再贅述.