一、概述
1、時間複雜度:一個程序(算法實現)在計算機上從開始運行到結束耗費的時間,且隨着輸入數據量的不斷增大(無限大),耗費時間的量級也不一樣,通過時間複雜度來判定一個程序實現消耗時間的量級程度,從而判斷該程序是否爲最佳實現(程序算法無錯,能夠正常執行時前提)。
2、空間複雜度:一個程序(算法實現)實現過程中所需的存儲空間,且隨着輸入數據量的不斷增大(無限大),耗費存儲空間的量級也不一樣,通過空間複雜度來判定一個程序實現需要的存儲空間的量級程度,從而判斷該程序是否爲最佳實現(程序算法無錯,能夠正常執行時前提)。
3、作爲一名研發人員,在實現重大業務算法時,尤其是高併發場景的需求,必須要考慮算法的時間複雜度(首要考慮),次之考慮空間複雜度
二、時間複雜度
1、時間頻度 (語句頻度):
一個算法中語句執行的次數,T(n),n 爲變量參數,代表輸入得規模,也可理解爲該算法實現的業務問題的規模
2、時間複雜度:T(n)=c * O(f(n)) (c爲常數) ,則 O(f(n)) 是T(n)的同數量級函數,引入同數量級函數爲了呈現時間頻度的變化規律。
定義有: T(n)=O(f(n)),稱O(f(n)) 爲算法的漸進時間複雜度,簡稱時間複雜度。
示例: O(n^2+n +1) = O (5n^2+n+3) = O (100n^2 + n) = O ( n2 ) (當n趨向無窮大)
3、時間複雜度從小到大排序: Ο(1)<Ο(log2n)<Ο(n)<Ο(nlog2n)<Ο(n2)<Ο(n3)<…<Ο(2n)<Ο(n!)
4、時間複雜度的計算
(1)確定業務實現邏輯
(2)選擇算法實現
(3)找出算法中的基本操作
(4)計算基本操作次數隨着輸入規模n(要解決的業務問題的規模)的變化,時間頻度的數量級 f(n)
(5)得出時間複雜度O(f(n))
示例1: 冒泡排序的時間複雜度
如初始數組是正序,一趟掃描進行n-1趟排序,但無移動 即可完成排序 ,((重要)基本操作爲:前一個數組元素與後一個數組元素對比)n-1次 ,得出O(n-1) ,時間複雜度爲O(n)
如初始數組是反序,則需要進行n-1次趟排序,每趟排序都需要進行 n- index 次比較 (index 當前數組座標是第幾個, 1<index<n-1 ),且每次都需要移動三次(n、 n+1 、temp),
由此得出基本操作爲 ,比較: n(n-1)/2 , 移動 3n(n-1)/2 ,得出 O(n(n-1)/2 + 3n(n-1)/2) ,時間複雜度爲 O(n^2)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public static void bubbleSort(int []arr) { int[] arr = {12,23,34,56,56,56,78}; for(int i =0;i<arr.length-1;i++) { for(int j=0;j<arr.length-i-1;j++) {//-1爲了防止溢出 if(arr[j]>arr[j+1]) { int temp = arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp; } } } } |
示例2: 類九九乘法表 java循環嵌套實現 ,時間複雜度O(n^2)
注:關於排序算法
常用的排序方法有:交換排序(冒泡排序、快速排序)、選擇排序(簡單選擇排序、堆排序)、插入排序(直接插入排序、希爾排序)、歸併排序、基數排序
三、空間複雜度
1、空間複雜度 即 程序實現過程需要的存儲空間,S(n)=O(f(n)),n 爲變量參數,代表輸入得規模,也可理解爲該算法實現的業務問題的規模
其中,f(n)爲語句關於n所佔存儲空間的函數。
2、隨着服務器硬件資源的發展,空間複雜度顯得不如時間複雜度重要了,所以沒有特殊說明的情況下算法“複雜度”通常指的是時間複雜度。
3、一個算法的空間複雜度只考慮在運行過程中爲局部變量分配的存儲空間的大小:形參、局部變量
4、空間複雜度計算
示例:冒泡排序 arr 、 i 、j、 temp ,所以空間複雜度爲 O(1)
示例2: 遞歸算法的空間複雜度:整個遞歸算法佔用的堆棧空間 ,加入一次調用所佔堆棧空間爲 M ,遞歸調用次數爲N,則整個遞歸算法佔用的空間爲 M*(N+1),然後再根據算法的規模n來計算空間複雜度
四、複雜度
時間複雜度,空間複雜度統稱爲算法的複雜度,一個算法在提升時間複雜度的同時,可能會造成空間複雜的性能下降,反之亦是如此,所以在實現一個算法時需綜合考慮業務需求、使用場景、性能要求及實現語言的特性(java,php,python)