二分

DomiSun發表於2024-09-23

二分

定義

二分查詢(binary search),也稱折半搜尋(half-interval search)、對數搜尋(logarithmic search),是用來在一個有序陣列中查詢某一元素的演算法。

過程

以在一個升序陣列中查詢一個數為例。

它每次考察陣列當前部分的中間元素,如果中間元素剛好是要找的,就結束搜尋過程;如果中間元素小於所查詢的值,那麼左側的只會更小,不會有所查詢的元素,只需到右側查詢;如果中間元素大於所查詢的值同理,只需到左側查詢。

時間複雜度

二分查詢的最優時間複雜度為 O(1)。

二分查詢的平均時間複雜度和最壞時間複雜度均為 O(log n)。因為在二分搜尋過程中,演算法每次都把查詢的區間減半,所以對於一個長度為 n 的陣列,至多會進行 O(log n) 次查詢。

空間複雜度

迭代版本的二分查詢的空間複雜度為 O(1)。

遞迴(無尾呼叫消除)版本的二分查詢的空間複雜度為 O(log n)。

整數二分演算法模板

bool check(int x) {/* ... */} // 檢查x是否滿足某種性質

// 區間[l, r]被劃分成[l, mid]和[mid + 1, r]時使用:
int bsearch_1(int l, int r)
{
    while (l < r)
    {
        int mid = l + r >> 1;
        if (check(mid)) r = mid;    // check()判斷mid是否滿足性質
        else l = mid + 1;
    }
    return l;
}
// 區間[l, r]被劃分成[l, mid - 1]和[mid, r]時使用:
int bsearch_2(int l, int r)
{
    while (l < r)
    {
        int mid = l + r + 1 >> 1;
        if (check(mid)) l = mid;
        else r = mid - 1;
    }
    return l;
}

浮點數二分演算法模板

bool check(double x) {/* ... */} // 檢查x是否滿足某種性質

double bsearch_3(double l, double r)
{
    const double eps = 1e-6;   // eps 表示精度,取決於題目對精度的要求
    while (r - l > eps)
    {
        double mid = (l + r) / 2;
        if (check(mid)) r = mid;
        else l = mid;
    }
    return l;
}

. . . . . .