巢狀迴圈

以下函式通過獲取每個元素來檢查陣列是否有任何重複,然後遍歷整個陣列以檢視該元素是否存在

_Bool contains_duplicates(const int *array, size_t len) {
    for (int i = 0; i < len - 1; i++) {
        for (int j = 0; j < len; j++) {
            if (i != j && array[i] == array[j]) {
                return 1;
            }
        }
    }
    return 0;
}

內迴圈在每次迭代時執行許多與 n 一致的操作。外迴圈也執行一些常量操作,並執行內迴圈 n 次。外環本身執行 3 次。因此內迴圈內的操作執行 4 次,外迴圈中的操作執行 5 次,並且對 i 的賦值執行一次。因此,複雜性將類似於 an^2 + bn + c,並且由於最高項是 n^2,因此 O 符號是 O(n^2)

你可能已經注意到,我們可以通過避免多次進行相同的比較來改進演算法。我們可以從內環中的 i + 1 開始,因為它之前的所有元素都已經針對所有陣列元素進行了檢查,包括索引 i + 1 中的元素。這允許我們放棄 i == j 支票。

_Bool faster_contains_duplicates(const int *array, size_t len) {
    for (int i = 0; i < len - 1; i++) {
        for (int j = i + 1; j < len; j++) {
            if (array[i] == array[j]) {
                return 1;
            }
        }
    }
    return 0;
}

顯然,第二個版本操作較少,因此效率更高。這如何轉化為 Big-O 表示法?那麼,現在內環體執行了 13 次。這仍然是二度多項式,所以仍然只是 O(n^2)。我們已經明顯降低了複雜性,因為我們將操作的數量大致除以 2,但我們仍然處於 Big-O 定義的相同複雜性類別中。為了將複雜性降低到較低的等級,我們需要將操作次數除以與趨勢無限的東西 15。