摘要:第三段,時間復雜度。五空間復雜度分析空間復雜度的話和時間復雜度類似推算。
一、前言
時間復雜度和空間復雜度,我們在大學里的算法與數據結構課程中已經學習過,這回根據項目工作中整理一下,這個估計只是一個粗略的估計分析,并不是一個準確的估計分析。
1、學習時間復雜度和空間復雜度是很有必要的,這個屬于算法與數據結構的范疇,學這個是為了解決代碼中的“快”和“省”的問題。這樣才能使你的代碼運行效率更高,占用空間更小。代碼執行效率需要通過復雜度分析。
2、數據規模的大小會影響到復雜度分析。比如排序,如果是一個有序的數組,執行效率會更高;如果數據量很少的時候,這個算法看不出性能上差別。
3、比如說不同物理機環境不一樣,比如i3,i5,i7的cpu等等,運行內存1G,2G,4G,8G等等;時間上肯定有差別。
二、大O的復雜度我們來看個簡單的例子,一個循環累加器。
function total(n) { var sum = 0; //t for (var i = 0; i < n; i++) { // nt sum += i; //nt } return sum; // t }
分析:假設每一行代碼執行耗時都一樣,為t,這樣整個代碼總執行時間為(t+nt+nt+t)=(2n+2)t。
我們再來看一個栗子:
function total(n) { var sum = 0; // t for (var i = 0; i < n; i++) { //nt for (var j = 0; j < n; j++) { //n*n*t sum = sum + i + j; //n*n*t } } return sum; //t }
分析:假設每一行代碼執行耗時都一樣,為t,這樣整個代碼總執行時間為(t+nt+nnt2+t)=(2nn+n+2)t。
從數學角度來看,我們可以得出個規律:代碼的總執行時間 T(n) 與每行代碼的執行次數成正比.
所以上邊兩個函數的執行時間可以標記為 T(n) = O(2n+2) 和 T(n) = O(2n*n+n+2)。這就是大 O 時間復雜度表示法,它不代表代碼真正的執行時間,而是表示代碼隨數據規模增長的變化趨勢,簡稱時間復雜度。
而且當 n 很大時,我們可以忽略常數項,只保留一個最大量級即可。所以上邊的代碼執行時間可以簡單標記為 T(n) = O(n) 和 T(n) = O(n2)。
三、時間復雜度分析 1、循環次數最多的代碼塊在分析的時候,只需要關心哪個代碼塊循環次數最多的那段代碼,比如說剛才的第一個例子,循環最多的代碼塊是這兩行,循環都是n次。
for (var i = 0; i < n; i++){ sum += i; }
執行了n次,所以事件復雜度就是O(n)。
2、最大值原則:總復雜度等于最大的代碼塊的復雜度function total(n) { // 第一個 for 循環 var sum1 = 0; for (var i = 0; i < n; i++) { for (var j = 0; j < n; j++) { sum1 = sum1 + i + j; } } // 第二個 for 循環 var sum2 = 0; for(var i=0;i<1000;i++) { sum2 = sum2 + i; } // 第三個 for 循環 var sum3 = 0; for (var i = 0; i < n; i++) { sum3 = sum3 + i; } return {sum1:sum1, sum2: sum2, sum3:sum3} }
分別分析每一段循環時間復雜度,取他們最大的量級決定整段代碼復雜度。
第一段,時間復雜度 O(n2)。
第二段,時間復雜度可以忽略,循環執行了 1000 次,是個常數量級,盡管對代碼的執行時間會有影響,但是當 n 無限大的時候,就可以忽略。
第三段,時間復雜度O(n)。
綜上所述,所以上述代碼的時間復雜度為 O(n2)。
3、乘法原則:嵌套代碼復雜度等于嵌套內外代碼復雜度乘積舉個例子:
function f(i) { var sum = 0; for (var j = 0; j < i; j++) { sum += i; } return sum; } function total(n) { var res = 0; for (var i = 0; i < n; i++) { res = res + f(i); // 調用 f 函數 } }
分析一下:total方法時間復雜度O(n),f方法的時間復雜度O(n)。
所以整段代碼的時間復雜度O(n2)。
四、常見的時間復雜度分析最高量級的復雜度,效率是遞減的
如上圖可以粗略的分為兩類,多項式量級和非多項式量級。其中,非多項式量級只有兩個:O(2n) 和 O(n!) 對應的增長率如下圖所示
當數據規模 n 增長時,非多項式量級的執行時間就會急劇增加,所以,非多項式量級的代碼算法是非常低效的算法。
1、常數階復雜度O(1)O(1) 只是常量級時間復雜度表示法,并不是代碼只有一行,舉個例子:
function total() { var sum = 0; for(var i=0;i<100;i++) { sum += i; } return sum; }
雖然有這么多行,即使 for 循環執行了 100 次,但是代碼的執行時間不隨 n 的增大而增長,所以這樣的代碼復雜度就為 O(1)。
2、對數階O(logn)和O(nlogn)(1)對數階時間復雜度的常見代碼如下:
function total1(n) { var sum = 0; var i = 1; while (i <= n) { sum += i; i = i * 2; } } function total2(n) { var sum = 0; for (var i = 1; i <= n; i = i * 2) { sum += i; } }
上面函數total1和total2有一個相同點:變量 i 從 1 開始取值,每循環一次乘以 2,當大于 n 時,循環結束。
所以真正循環了x次。2x =n;,所以 x = log2n。
所以上面兩個函數時間復雜度都是 O(log2n)。
(2)我們在舉個例子:
function total1(n) { var sum = 0; var i = 1; while (i <= n) { sum += i; i = i * 3; } } function total2(n) { var sum = 0; for (var i = 1; i <= n; i = i * 3) { sum += i; } }
同理可知:這兩個函數的時間復雜度為 O(log3n) 。
由于我們可以忽略常數,也可以忽略對數中的底數,所以在對數階復雜度中,統一表示為 O(logn);那 O(nlogn) 的含義就很明確了,時間復雜度 為O(logn) 的代碼執行了 n 次。
3、其他復雜度O(m+n)和O(m*n)舉個例子:
function total(m,n) { var sum1 = 0; for (var i = 0; i < n; i++) { sum1 += i; } var sum2 = 0; for (var i = 0; i < m; i++) { sum2 += i; } return sum1 + sum2; }
因為我們無法評估 m 和 n 誰的量級比較大,所以就不能忽略掉其中一個,這個函數的復雜度是有兩個數據的量級來決定的,所以此函數的時間復雜度為 O(m+n);那么 O(m*n) 的時間復雜度類似。
五、空間復雜度分析空間復雜度的話和時間復雜度類似推算。 所謂空間復雜度就是表示算法的存儲空間和數據規模之間的關系。
舉個例子:
function initArr(n) { var arr = []; for (var i = 0; i < n; i++) { arr[i] = i; } }
時間復雜度的推算,忽略掉常數量級,每次數組賦值都會申請一個空間存儲變量,所以此函數的空間復雜度為 O(n)。
常見的空間復雜度只有 O(1)、O(n)、O(n2)。其他的話很少會用到。
六、復雜度優化function total(n) { var sum = 0; for (var i = 1; i <= n; i++) { sum += i; } return sum; }
這段代碼我們很容易知道時間復雜度 O(n)。
但是我想把復雜度降一降,降低到常數階O(1)。
其實求和怎么求呢?等比數列,直接用公式,這就說明了數學好的人,算法應該高level點。
function total(n) { var sum = n*(n+1)/2 return sum; }
上面函數的時間復雜度僅僅為 O(1),在數據規模比較龐大的時候,下面的函數是不是明顯比上面的函數運算效率更高呢。
七、總結分析算法執行效率與數據規模之間的增長關系,可以粗略的表示,越高階復雜度的算法,執行效率越低。
復雜度學習之后,有時候可以避免寫出效率低的代碼。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/105934.html
摘要:散列表上面的地圖向我們展示了如何用廣度優先搜索的思想找到北京到廣州的最短路線。在廣度優先搜索中,我們需要用到隊列的這種思想來實現查找。建立了下面這個模型武漢廣州西藏上海上海武漢廣州代碼完整實現,利用遞歸和廣度優先搜索的思想實現。 什么是廣度優先搜索? 如果只是是背概念,幼兒園的小朋友都能背下來念給你聽。 假設看這篇文章的都和我一樣是個前端工程師,我們要從廣度優先搜索(BFS)中學到什么...
摘要:也就是說,它通過計算一個關于鍵值的函數,將所需查詢的數據映射到表中一個位置來訪問記錄,這加快了查找速度。這個映射函數稱做散列函數,存放記錄的數組稱做散列表。如果對象沒有該實例化該處為一對象如果該不存在就增加一個數量 本系列一系列文章的收集關于javascript中的數據結構 如果你對數據結構不太熟悉 可以看這篇文章如果你只想看代碼 可以看這篇文章如果你只想star 可以去這里 什么是數...
摘要:之所以把計數排序桶排序基數排序放在一起比較,是因為它們的平均時間復雜度都為。動畫計數排序思想找出待排序的數組中最大和最小的元素。桶排序計數排序能派上用場嗎手機號碼有位,范圍太大,顯然不適合用這兩種排序算法。 showImg(https://segmentfault.com/img/bVbuF9e?w=900&h=500); 1. 前言 算法為王。 想學好前端,先練好內功,只有內功深厚者...
摘要:小鹿題目假設你正在爬樓梯。需要階你才能到達樓頂。你有多少種不同的方法可以爬到樓頂呢注意給定是一個正整數。算法思路二種解決思路,第一利用遞歸第二利用動態規劃。就是因為有了重復元素的計算,導致了時間復雜度成指數的增長。 Time:2019/4/12Title:Clibing SrairsDifficulty: EasyAuthor:小鹿 題目:Climbing Stairs You a...
閱讀 2382·2021-09-30 09:47
閱讀 1373·2021-09-28 09:35
閱讀 3245·2021-09-22 15:57
閱讀 2495·2021-09-22 14:59
閱讀 3641·2021-09-07 10:25
閱讀 3076·2021-09-03 10:48
閱讀 3041·2021-08-26 14:14
閱讀 942·2019-08-30 15:55