複雜度分析(下)

2021-08-28 20:35:47 字數 2920 閱讀 7313

最好、最壞時間複雜度分析

// n 表示陣列 array 的長度

int find(int array, int n, int x)

return pos;

}

上面**的功能是在乙個陣列中查詢乙個變數x出現的位置,如果沒有找到,返回-1。這段**的時間複雜度應該為o(n),其中n為數字的長度。

但是我們在陣列中查詢資料,並不需要每次都把陣列都遍歷一遍,因為有的資料在中途就找到,可以提前退出的,所以上面的**寫的不好,看下面的

// n 表示陣列 array 的長度

int find(int array, int n, int x)

} return pos;

}

我們發現,在找到資料後,就退出了迴圈。但是這個**的時間複雜度就不能簡單看成 o(n)了。因為我們沒有辦法判斷在哪個位置上找到這個元素,可能陣列的第乙個位置就是要找的資料,然後不需要遍歷後面的n-1個資料,那麼時間複雜度是o(1)。如果陣列中沒有找到這個元素,就需要把陣列整個遍歷一遍,那麼時間複雜度就是o(n)。所以我們發現,不同情況,時間複雜度是不一樣的。

為了表示**在不同情況下的不同時間複雜度,我們需要引入三個概念:最好情況時間複雜度、最壞情況時間複雜度和平均情況時間複雜度。

同理,最壞情況時間複雜度就是,在最糟糕的情況下,執行這段**的時間複雜度。像上面的例子中,如果要查詢的元素沒有在陣列中,就需要遍歷整個陣列。

平均情況時間複雜度

最好情況時間複雜度和最壞情況時間複雜度都是在極端情況下的**的複雜度,發生的概率不大。為了更好的表示平均情況下的複雜度,需要引入平均情況時間複雜度。

還拿上面的例子舉例。要查詢的元素在陣列中的位置,有n+1種情況:在陣列的0~n-1位置中和不在陣列中,共n+1種情況。把每種情況下,查詢需要遍歷的元素個數累加,然後除以 n+1,就能得到需要遍歷的元素的個數的平均值。

因為大o表示法,可以省略係數,所以平均情況時間複雜度為 o(n)。

但是這個計算過程是不嚴謹的,因為上面的n+1種情況出現的概率並非都一樣。要查詢的元素要麼在陣列中,要麼不在陣列中,為了方便,假設在陣列中和不在陣列中的概率都為1/2。要查詢的元素出現在 0~n-1個位置的概率也都是一樣的,為 1/n。所以要查詢的元素出現在 0~n-1中任意位置的概率是 1/(2n)。將上面的計算邏輯修改如下:

這個值就是概率論中的加權平均值,也叫期望值,所以平均時間複雜度的全程應該叫加權平均時間複雜度或期望時間複雜度。

我們發現,引入概率後,平均值為(3n+1)/4。用大o表示法表示,去掉係數和常量,這段**的時間複雜度依然是 o(n)。

其實,大多數情況,並不需要區分最好、最壞、平均情況時間複雜度。很多時候,用乙個複雜度就可以滿足。只有同乙個**在不同情況下,時間複雜度有量級的差距時,才引入這三個時間複雜度。

均攤時間複雜度

// array 表示乙個長度為 n 的陣列

// **中的 array.length 就等於 n

int array = new int[n];

int count = 0;

void insert(int val)

array[0] = sum;

count = 1;

}array[count] = val;

++count;

}

上面的**實現的是往陣列中插入資料的功能。當陣列滿了之後,用for迴圈遍歷陣列求和,並清空陣列,將求和之後的sum值放到陣列的第乙個位置,然後再將新的資料插入。但如果陣列一開始就有空閒空間,則直接將資料插入陣列。

分析這個**的時間複雜度。最好的情況下,陣列中有空閒空間,直接將資料插入到陣列下標為count的位置,所以最好情況時間複雜度是o(1)。最壞的情況下,陣列中沒有空閒空間了,需要先遍歷陣列求和,然後再將陣列插入,所以最壞情況的時間複雜度是 o(n)。平均時間複雜度分析如下:

假設陣列長度為n,根據陣列插入的位置不同,分為n種情況,每種情況的時間複雜度為o(1)。還有一種情況就是,陣列沒有空閒空間了,這個時候時間複雜度是o(n)。這n+1種情況發生的概率相同,都是 1/(n+1)。所以平均時間複雜度為:

這個insert()和前面的find()是有區別的:

①find()在極端情況,複雜度才是o(1)。而insert()在大部分情況下都是o(1),只有個別情況才是o(n)

②insert()函式,o(1)時間複雜度的插入和o(n)時間複雜度的插入,出現的頻率很有規律,並且有一定的前後時序關係,一般都是乙個o(n)插入後跟著n-1個o(1)插入,如此迴圈。

所以針對insert()這種情況,不需要像find()那樣根據概率計算平均時間複雜度。而是引入一種更加簡單的分析方法:攤還分析法,通過攤還分析法得到的時間複雜度叫均攤時間複雜度。

攤還分析法的使用:

還看insert()這個函式,每一次o(n)的插入,後面會跟著n-1次o(1)的插入操作,所以把耗時較多的那次操作均攤到接下來的n-1次耗時較少的操作上,均攤下來,這一組連續的操作的均攤時間複雜度就是o(1)。

攤還分析法的使用場景:

對於乙個資料結構進行一組連續的操作中,大部分情況下時間複雜度都很低,只有個別情況下時間複雜度比較高,而且這些操作之間存在前後連貫的時序關係,這個時候,就可以將這一組操作放在一起分析,看是否能把較高時間複雜度的操作,平攤到其他不耗時的操作中。而且,在能夠應用均攤分析法的場景中,一般均攤時間複雜度等於最好情況時間複雜度。

複雜度分析 時間複雜度分析和空間複雜度分析

其實,只要講到資料結構與演算法,就一定離不開時間 空間複雜度分析。而且我個人認為,複雜度分析是整個演算法學習的精髓,只要掌握了它,資料結構和演算法的內容基本上就掌握了一半。1.時間複雜度分析 對於剛才羅列的複雜度量級,我們可以粗略地分為兩類,多項式量級和非多項式量級。其中,非多項式量級只有兩個 o ...

二 複雜度分析 下

這篇從要從四個方面去分析複雜度 最好情況時間複雜度 最壞情況時間複雜度 平均情況時間複雜度 均攤時間複雜度。首先分析以下例子 由於在迴圈中有乙個 if 判斷語句,所以無法粗略的定義該段 的時間複雜度為o n 在這裡我們就需要引入三個概念 最好情況時間複雜度 最壞情況時間複雜度 平均情況時間複雜度。由...

筆記 複雜度分析(下)

前言 四個複雜度分析 1.最壞情況時間複雜度 在最壞情況下執行的時間複雜度。2.最好情況時間複雜度 在最理想情況下執行的時間複雜度。3.平均時間複雜度 加權平均時間複雜度 在所有情況下執行次數的加權平均值表示的時間複雜度。4.均攤時間複雜度 在 執行的所有複雜度情況中絕大部分是低階別的複雜度,個別情...