1. 程式人生 > >演算法基礎筆記_時間複雜度

演算法基礎筆記_時間複雜度

大O的理解:

  • n表示資料規模
  • O(f(n)) 表示執行演算法所需要執行的指令數(執行時間),和f(n)成正比
  • O(f(n)) 可以理解為: t = a*f(n) + b = f(n)
  • 簡單驗證程式演算法複雜度的方法:將資料規模依次成倍增長,檢視執行時間的增長規律,或作出 t-n 的座標圖觀察。
  • “均攤複雜度” 和 “複雜度震盪”
  • 二分查詢法 O(logn)                       所需執行指令數:a*logn
  • 尋找陣列中的最大/最小值 O(n)     所需執行指令數:b*n
  • 歸併排序演算法 O(nlogn)                 所需指令數:c*nlogn
  • 選擇排序法 O (n^2)                       所需指令數:d*n^2

        O(nlogn+n) = O(nlogn)

        O(nlogn+n^2) = O(n^2)

      資料規模量不一致時:

        O(AlogA+B) != O(AlogA)

        O(AlogA+B^2) != O(B^2)

     對鄰接表實現的圖的遍歷:

     時間複雜度:O(V+E)

         V:頂點個數; E:邊的個數

二分查詢法的時間複雜度是O(logn)的理解:

     二分查詢的執行步驟:在n個元素中尋找 -> 在n/2個元素中尋找 -> 在n/4個元素中尋找 -> ... 在一個元素中尋找

                                         n經過 t 次“除以2”操作後等於1   ->   n*(\frac{1}{2})^t=1  ->   t=log {_{2}}n=O(logn)

    可推:n經過 t 次 “除以k” 的操作後等於1 —> 時間複雜度:t=log {_{k}}n=O(logn)

    注:t=log {_{a}}n,t=log {_{b}}n \rightarrow O(logn) ,   因為 log {_{a}}n=log {_{a}}b*log {_{b}}n, 而 log {_{a}}b 是一個常數。

 

O(nlogn)的例子:外層迴圈是一個t次“乘以2”操作到達n的過程,是一個O(logn), 內層迴圈是一個O(n),故雙層迴圈巢狀後為O(nlogn)

 for(int i=1; i<n; i+=i){
    for(int j=1; j<n; j++){
        //do something
    }
 }

O(\sqrt{n})的例子:i一步一步到達\sqrt{n}

for(int i=1; i*i<n; i++){
    //do something
}

 

遞迴演算法的時間複雜度分析: 

  • 遞迴函式中,只進行一次遞迴呼叫,遞迴深度為depth, 在每個遞迴函式中,時間複雜度為T,則總體的時間複雜度為O(T*depth)
  • 遞迴函式中,多次進行遞迴呼叫,要考慮遞迴深度、遞迴呼叫次數、每個遞迴函式中的時間複雜度。 具體可查閱“主定理”知識。

參考:各種排序演算法效能之間的比較

          o(1), o(n), o(logn), o(nlogn)

一個時間複雜度問題:

      有一個字串陣列,將陣列中每一個字串按照字母排序;之後再將整個字串陣列按照字典序排序,求整個操作的時間複雜度。 

錯誤解法:O(n*nlogn+nlogn)=O(n^2logn)

正確思路:假設最長的字串長度為s, 陣列中有n個字串;(排序演算法中,nlogn表示的是比較的次數)

                  對每個字串排序:O(slogs),而陣列中有n個字串,則:O(n*slogs);

                  將整個字串陣列按照字典序排序:O(s*nlogn)

                  綜上:O(n*slogs) + O(s*nlogn) = O(n*s*logs+s*n*logn)

演算法複雜度在有些情況下是用例相關的 :

  插入排序演算法O(n^2):                    快速排序演算法O(nlogn):                                               

     最差情況: O(n^2);                           最差情況: O(n^2);

     最好情況: O(n);                              最好情況: O(nlogn)

     平均情況: O(n^2)                           平均情況: O(nlogn)

對資料規模的概念: 

   如果想要在1s之內解決問題:

  • O(n^2)的演算法可以處理大約10^4級別的資料;
  • O(n)的演算法可以處理大約10^8級別的資料;
  • O(nlogn)的演算法可以處理大約10^7級別的資料;

  為了保險起見,可以降低一個數量級。

空間複雜度: 

  • 多開一個輔助的陣列:O(n)
  • 多開一個輔助的二維陣列:O(n^2)
  • 多開常數空間:O(1)   即開一些臨時的變數儲存一些臨時的值,不論資料規模n的大小,開出的儲存空間是一定的。

  注意:遞迴的呼叫是有空間代價的,遞迴過程中未退出的狀態要壓入系統棧中,空間複雜的與遞迴的深度有關。