1. 程式人生 > >減而治之 - 二分查找 - lower_bound實現原理

減而治之 - 二分查找 - lower_bound實現原理

算法 lse splay col while pan 有序 實現 利用

本文介紹利用二分實現 lower_bound 的原理。

lower_bound(T * a, T & t, int lo, int hi) 的功能是:在某個有序數組 a[lo, hi) 的範圍內,查找不小於 t 的最小元素或最小元素位置。這可以用二分來實現。

技術分享圖片

算法可以這樣理解。我們維護兩個界限,分別為:

L:保證 ≤ L 位置的元素都小於 t;
R:保證 ≥ R 位置的元素都大於等於 t。

我們不斷改變 L 和 R 的位置,使 L 和 R 不斷靠近,直至 L + 1 = R 時,R 即為我們要查找的目標位置。

假想 lo-1 位置存放著一個 -∞ 的哨兵,hi 位置存放著一個 +∞ 的哨兵。初始時 L = lo - 1, R = hi。

如何調整 L 和 R 的位置呢?每次觀察區間 [L, R] 中間位置的元素,即 A[mid = (L+R)/2] 的元素與 t 的大小,因為 A 的有序性:

若 A[mid] ≥ t, 我們可以把 R 替換為 mid。
若 A[mid] < t,我們可以把 L 替換為 mid。
這樣,L 和 R 不斷靠近,直至 L + 1 == R,則結束,R 則為我們要找的目標位置。

C++代碼示例(設要查找的類型是整數):

/* 返回按升序排列的 a[lo, hi) 中不小於 t 的最小值的下標。若不存在,則返回hi */
int lowerBound(int * a, int t, int lo, int hi)
{    
    int L = lo - 1, R = hi;
    while ( L + 1 < R )
    {
        int mid = (L + R) >> 1;
        if ( a[mid] < t )
            L = mid;
        
else R = mid; } return R; }

減而治之 - 二分查找 - lower_bound實現原理