【簡單算法】什么是復雜度?


在上一篇文章里,有看到一個簡單算法題的2個解法,我們運用了復雜度分析來判斷哪個解法更合適。
這里的復雜度,就是用於衡量程序的運行效率的重要度量因素。

雖然有句俗話“不管是白貓還是黑貓,抓到老鼠就是好貓”,這句話是站在結果導向的,沒錯。但是如果
有個程序要去處理海量數據,一個程序員寫的要執行2天,而另一個程序員只要半小時,那么第二種顯然更適合
我們的實際需求。

一、什么是復雜度

復雜度是一個關於輸入數據量n的函數。

要表示復雜度很簡單,用大寫O加上括號O()將復雜度包起來就好了。比如這個代碼的復雜度是f(n),那就可以寫成
O(f(n))

在計算復雜度的時候,有三點需要我們記住:

  • 復雜度與具體常系數無關
  • 多項式級復雜度相加,選擇高者為結果
  • O(1)表示特殊復雜度

1、復雜度與具體常系數無關

舉個例子,將一個列表反轉,不用reverse()。

def demo_1():
    a = [1, 2, 3, 4, 5]
    b = [0 for x in range(0,5)]  #第一個for循環
    n = len(a)
    for i in range(n):   # 第二個for循環
        b[n - i - 1] = a[i]
    print(b)

if __name__ == "__main__":
    demo_1()

===============運行結果==================
D:\Programs\Python\Python36\python.exe D:/練習/leecode/fuzadu.py
[5, 4, 3, 2, 1]

Process finished with exit code 0

可以看到我先用了一個for循環創建了一個跟a列表等長度,元素全是0的列表。
然后再用一個for循環將a里的元素倒序放入b,最終得到一個跟a反序的列表。

其中,每一個for循環的時間復雜度都是O(n),2個加起來就是O(n)+O(n),也等於O(n+n),也等於O(2n)
也就是相當於 一段 O(n)復雜度的代碼先后執行兩遍,它們的復雜度是一致的。

2、多項式級復雜度相加,選擇高者為結果

有了上面的例子,這個也就好理解了。
假設,一個算法的復雜度是O(n²)+O(n),那么可以知道,當n越來越大,也就是輸入的數據量越來越大時,n^2的變化率要比n大的多,
所以,這時候我們只取變化率更大的n^2來表示復雜度即可,也就是O(n²)+O(n)等同於O(n²)

3、O(1)表示特殊復雜度

還是借助上面的反轉問題,這里再使用第二種解法。

def demo_2():
    a = [1, 2, 3, 4, 5]
    tmp = 0
    n= len(a)

    for i in range(n//2):    #  // 表示整數除法,返回不大於結果的一個最大整數
        tmp = a[i]
        a[i] = a[n -i -1]
        a[n -i -1] = tmp
    print(a)

if __name__ == "__main__":
    demo_2()

==============運行結果==============
D:\Programs\Python\Python36\python.exe D:/練習/leecode/fuzadu.py
[5, 4, 3, 2, 1]

Process finished with exit code 0

跟第一個解法相比,第二個解法少了一個for循環,而且循環次數只是到了列表的一半,那么時間復雜度就是O(n/2)
由於復雜度與具體的常系數無關的性質,這段代碼的時間復雜度還是 O(n)

但是在空間復雜度上,第二個解法開辟了一個新的變量tmp,它與數組長度無關。
輸入是 5 個元素的數組,需要一個tmp變量輸入是 50 個元素的數組,同樣只需要一個tmp變量。

因此,空間復雜度與輸入數組長度無關,這就是 O(1)

二、分析復雜度

這里就直接上一些經驗性的結論,可以直接拿過來用的:

  • 一個順序結構的代碼,時間復雜度是 O(1)
  • 一個簡單的 for 循環,時間復雜度是 O(n)
  • 兩個順序執行的 for 循環,時間復雜度是 O(n)+O(n)=O(2n),其實也是 O(n)
  • 兩個嵌套的 for 循環,時間復雜度是 O(n²)
  • 二分查找,時間復雜度都是 O(logn)

趁熱打鐵,分析一下下面代碼的復雜度:

for (i = 0; i < n; i++) {
    for (j = 0; j < n; j++) {
        for (k = 0; k < n; k++) {
        }
        for (m = 0; m < n; m++) {
        }
    }
}

可以先從最里面看,最內層是2個順序結構的for循環,復雜度是O(n)
中間這層的又嵌套了一個for循環,所以這時候復雜度就變成了O(n^2)
最后,最外層又嵌套了一個for循環,所以最終的復雜度就是O(n^3)

雖然測試工程師的代碼對於復雜度要求不高甚至說非常低,但是我覺得理解復雜度,並且會做一些簡單的分析
還是很有必要的。


免責聲明!

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



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