極客時間課程《數據結構與算法之美》01 - 復雜度


復雜度計算

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)。。。。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM