1. 程式人生 > >倍增搜尋_形式化分析

倍增搜尋_形式化分析

本文給出整數集上倍增搜尋的常見形式, 正確性證明和時間複雜度分析..

一: 演算法ForeardDoubleSearch(l, r, p)//正向倍增

    如不做特殊說明, 下面的敘述中約定: 序列S=a_{1}...a_{n}, 定義函式p(x), 滿足, 存在正整數k, 使得當x\in \left \{ a_{1}, a_{2}, ..., a_{k} \right \}時p(x) = true,當x\in \left \{ a_{k + 1}, a_{k + 2}, ..., a_{n} \right \}時p(x) = false

  1. ForwardDoubleSearch(l, r, p)//初始引數l = 1, r = n, p為判定函式,
  2.         begin = l, len = 2
  3.         while len >= 2
  4.                 if p(begin + len - 1)
  5.                         begin = begin + len - 1, len = len\times 2
  6.                 else
  7.                         len = \frac{len}{2}
  8.         return begin

對於上述演算法有下述重要結論成立,

    (1): 如果對任意a_{i}, 1 =< i <= n, 均有p(a_{i}) = 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 \neq

k, 對於之後的每次迴圈考慮如下迴圈不變式:

    迴圈不變式: 每次第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值分別記為len_{s}, len_{s + 1}, len_{s + 2}, len_{s + 3}, len_{s + 4}, len_{s + 5}, 滿足len_{s + 1} = \frac{len_{s}}{2}len_{s + 2} = \frac{len_{s}}{2}len_{s + 3} = \frac{len_{s}}{2} 或len_{s + 4} = \frac{len_{s}}{2}len_{s + 5} = \frac{len_{s}}{2}, 下面給出此推論的證明.

    如果第s次迴圈頭檢測之前p(begin + len - 1)為false, 那麼第s次迴圈中執行len = len / 2, 從而len_{s + 1} = \frac{len_{s}}{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次迴圈頭檢測之前

len = \frac{L}{2}, 從而len_{s + 5} = \frac{len_{s}}{2}.

     (ii)(i)如果在第s + 2次迴圈中p(begin + len - 1)不成立, 那麼在第s + 2次迴圈中執行len = len / 2, 故在第s + 3次迴圈頭檢測之前len = len = \frac{L}{2}, 從而len_{s + 3} = \frac{len_{s}}{2}

     綜上述, 推論1得證.

     根據之前給出的迴圈不變式和推論1很容易證明第3至7行迴圈經過O(lg(k))次迭代後終止, 且終止時begin = k, 具體證明過程不再贅述.

一: 演算法ReverseDoubleSearch(l, r, p)//反向倍增

    如不做特殊說明, 下面的敘述中約定: 序列S=a_{1}...a_{n}, 定義函式p(x), 滿足, 存在正整數k, 使得當x\in \left \{ a_{1}, a_{2}, ..., a_{k} \right \}時p(x) = false,當x\in \left \{ a_{k + 1}, a_{k + 2}, ..., a_{n} \right \}時p(x) = true

  1. ReverseDoubleSearch(l, r, p)//初始引數l = 1, r = n, p為判定函式,
  2.         begin = r, len = 2
  3.         while len >= 2
  4.                 if p(begin - len + 1)
  5.                         begin = begin - len + 1, len = len\times 2
  6.                 else
  7.                         len = \frac{len}{2}
  8.         return begin

對於上述演算法有下述重要結論成立,

    (1): 如果對任意a_{i}, 1 =< i <= n, 均有p(a_{i}) = 0, 那麼第3至7行迴圈結束時l = r = n, 否則第3至7行迴圈經過O(lg(k))次迭代後終止, 且終止時begin = k, 後者的證明可直接類比對於演算法ForeardDoubleSearch(l, r, p)的分析過程, 此處不再贅述.