i=1; while (i <= n) { i = i * 2; }
實際效果:java
2^{0} * 2^{1} * 2^{2} ··· 2^{k} ··· 2^{x}= n
經過 2x=n 求解 x 。
x=log2n,因此,這段代碼的時間複雜度就是O (log2n)。數組
無論底數是幾,全部對數階的時間複雜度都記爲
O (logn)。由於
O (log3n) = O(C * log2n),使用大O標記複雜度的時候,能夠忽略係數,因此贊成表示爲O (logn)。數據結構
好比,歸併排序、快速排序的時間複雜度都是 O (nlogn)。code
int cal(int m, int n) { int sum_1 = 0; int i = 1; for (; i < m; ++i) { sum_1 = sum_1 + i; } int sum_2 = 0; int j = 1; for (; j < n; ++j) { sum_2 = sum_2 + j; } return sum_1 + sum_2; }
其中m和n是表示兩個數據規模,沒法事先評估m和n哪一個大,因此不能隨意省略,故,上面代碼的時間複雜度就是 O (m+n)。排序
void print(int n) { int i = 0; int [ ] a = new int[n]; for (i; i <n; ++i) { a[i] = i * i; } for (i = n-1; i >= 0; --i) { print out a[i] } }
第2行申請一個空間存儲變量i,能夠忽略,和n無關。
第三行申請了大小爲n的int類型數組,除此以外,無更多空間佔用。故複雜度爲O(n)。class
大部分狀況下,沒必要區分最好、最壞、平均狀況時間複雜度三種狀況。變量
// array 表示一個長度爲 n 的數組 // 代碼中的 array.length 就等於 n //這段代碼僅僅是王爭給的例子,沒什麼特殊實際意義。 int[] array = new int[n]; int count = 0; void insert(int val) { if (count == array.length) { int sum = 0; for (int i = 0; i < array.length; ++i) { sum = sum + array[i]; } array[0] = sum; count = 1; } array[count] = val; ++count; }
咱們仍是繼續看在數組中插入數據的這個例子。每一次 O (n) 的插入操做,都會跟着 n-1 次 O (1) 的插入操做,因此把耗時多的那次操做均攤到接下來的 n-1 次耗時少的操做上,均攤下來,這一組連續的操做的均攤時間複雜度就是 O (1)。這就是均攤分析的大體思路。方法
對一個數據結構進行一組連續操做中,大部分狀況下時間複雜度都很低,只有個別狀況下時間複雜度比較高,並且這些操做之間存在先後連貫的時序關係,這個時候,咱們就能夠將這一組操做放在一起分析,看是否能將較高時間複雜度那次操做的耗時,平攤到其餘那些時間複雜度比較低的操做上。並且,在可以應用均攤時間複雜度分析的場合,通常均攤時間複雜度就等於最好狀況時間複雜度。數據
均攤時間複雜度就是一種特殊的平均時間複雜度,不必花太多精力去區分它們。最應該掌握的是它的分析方法,攤還分析。至於分析出來的結果是叫平均仍是叫均攤,這只是個說法,並不重要。時間
對於可反覆讀寫的存儲空間,認爲它空即爲空。清空數組有時候並不須要置爲0,或某個值。把下標指到第一個位置就能夠。
留言體會:平均和平攤基本就是一個概念,平攤是特殊的平均。在分析時間複雜度是 O (1) 仍是 O (n) 的時候最簡單就是憑感受,,,,,,,,出現 O (1) 的次數遠大於出現 O (n) 出現的次數,那麼平均平攤時間複雜度就是 O (1)。。。。