10.算法分析

算法時間複雜度和空間複雜度python

  1. 瞭解時間複雜度對算法的選用會頗有幫助,好比說以前怎麼樣選擇數據結構,都是經過每一個操做的時間複雜度的分析來看是否是知足需求,確定的是,在知足需求的狀況下,時間複雜度越優越好,操做次數越少越好。算法

  2. 大O是什麼?能夠理解爲操做次數與數據個數的比例關係;O(1)是有限次數的操做;O(n)是操做正比於你的元素。數組

  3. 大O表示法:數據結構

    參考《算法導論》的列子:考慮計算一個n * n的矩陣全部元素的和:ide

image.png

 列舉兩種方式:
函數

# version1
total_sum = 0
for i in range(n):
    row_sum[i] = 0
    for j in range(n):
        row_sum[i] = row_sum[i] + matrix[i, j]
        total_sum = total_sum + matrix[i, j]

# version2
total_sum = 0
for i in range(n):
    row_sum[i] = 0
    for j in range(n):
        row_sum[i] = row_sum[i] + matrix[i, j]
    total_sum = total_sum + row_sum[i]    # 注意這裏和上邊的不一樣

兩種方式的主要區別在最後一行,優化

    第一個方式:假設矩陣是n*n的,這嵌套是在兩層循環裏面,並且每一步都循環n次,能夠認爲它是一個n*n的,循環兩次,即 (2n)*n的時間複雜度。spa

    第二個方式:假設矩陣是n*n的,能看出最後一行不在上面的循環裏面,上面的循環執行了n*n(嵌套在兩層循環裏面),最後一行是執行n次,因此他是n*n+n的時間複雜度。orm

若是數據量很小,可能感受不出差別,可是若是放大n的增加的時候,總的操做次數就很明顯區別了:blog

image.png

一般不關係每一個算法執行了多少次,更關心隨輸入規模的增長算法運行的時間將以什麼樣的速度增長,因此定義了一個符號,大O符號。


4. 如何計算時間複雜度

上面舉例2個版本的計算矩陣和的代碼,有兩個公式:

① 2n * n = 2n2

② n+n*n = n+n2

當n很是大的時候,n*n(即n的平方)的數值將佔主導,能夠忽略單個n的影響:

n+n2<= 2n2

能夠認爲兩個算法的時間複雜度都爲O(n2)


5.經常使用的時間複雜度

列舉一些經常使用的時間複雜度,按照增加速度排序,平常咱們的業務代碼中最經常使用的是指數以前的複雜度,指數和階乘的增加速度很是快, 當輸入比較大的時候用在業務代碼裏是不可接受的。

O

名稱

舉例 補充
1 常量時間 一次賦值 nlogn如下的這些時間複雜度都是比較佔優點的。
logn 對數時間 折半查找
n 線性時間 線性查找
nlogn 對數線性時間 快速排序
n2 平方 兩重循環 越向上增加的越快那那怕是計算機很是快,依然要花不少時間運行。
n3 立方

三重循環

2n 指數
遞歸求斐波那契數列
n! 階乘 旅行商問題
O(1)  固定時間內的一次操做,好比:一次賦值,一次加法,幾回加法操做。
O(logn) 二分查找,操做一個有序數組的時候,每次均可以把它折半。
O(n) 查找都須要從頭查到尾,找到了才能退出。
O(nlogn) 快速排序或歸併
O(n2) 兩重循環嵌套
O(n3)

三重嵌套

O(2n) 指數就有一些遞歸算法,沒有優化的遞歸
O(n!) 旅行商問題,學術界討論會比較多,工程會少一些


6.空間複雜度

    相比於時間,空間不少時候,不是主要的考慮因素,用戶老爺們都等不及,並且如今存儲都愈來愈便宜了,爲了提高響應速度,能可多用一點空間,因此空間複雜度討論的少一些;固然,若是數據量很是很是大,也會考慮空間佔用的問題。


常見的空間複雜度的增加趨勢圖:

函數增加趨勢圖

因此,工程上能接受的都是 nlogn 如下的空間複雜度,圖中nlogn,n,log2n這些。

相關文章
相關標籤/搜索