復雜度計算
O (logn)
i=1;
while (i <= n) {
i = i * 2;
}
實際效果:
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)。
O(m+n)、O(m*n)
代碼復雜度由兩個數據的規模來決定。
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)。
均攤時間復雜度
大部分情況下,不必區分最好、最壞、平均情況時間復雜度三種情況。
// 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)。。。。