成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

用 JavaScript 學(xué)習(xí)算法復(fù)雜度

開發(fā) 前端 算法
在本文中,我們將探討 “二次方” 和 “n log(n)” 等術(shù)語在算法中的含義。在后面的例子中,我將引用這兩個數(shù)組,一個包含 5 個元素,另一個包含 50 個元素。我還會用到 JavaScript 中方便的 performance API 來衡量執(zhí)行時間的差異。

 在本文中,我們將探討 “二次方” 和 “n log(n)” 等術(shù)語在算法中的含義。

[[314140]]

在后面的例子中,我將引用這兩個數(shù)組,一個包含 5 個元素,另一個包含 50 個元素。我還會用到 JavaScript 中方便的 performance API 來衡量執(zhí)行時間的差異。

 

  1. const smArr = [5, 3, 2, 35, 2]; 
  2.  
  3. const bigArr = [5, 3, 2, 35, 2, 5, 3, 2, 35, 2, 5, 3, 2, 35, 2, 5, 3, 2, 35, 2, 5, 3, 2, 35, 2, 5, 3, 2, 35, 2, 5, 3, 2, 35, 2, 5, 3, 2, 35, 2, 5, 3, 2, 35, 2, 5, 3, 2, 35, 2]; 

 

什么是 Big O 符號?

Big O 表示法是用來表示隨著數(shù)據(jù)集的增加,計算任務(wù)難度總體增長的一種方式。盡管還有其他表示法,但通常 big O 表示法是最常用的,因為它著眼于最壞的情況,更容易量化和考慮。最壞的情況意味著完成任務(wù)需要最多的操作次數(shù);如果你在一秒鐘內(nèi)就能恢復(fù)打亂魔方,那么你只擰了一圈的話,不能說自己是做得最好的。

當(dāng)你進一步了解算法時,就會發(fā)現(xiàn)這非常有用,因為在理解這種關(guān)系的同時去編寫代碼,就能知道時間都花在了什么地方。

當(dāng)你了解更多有關(guān) Big O 表示法的信息時,可能會看到下圖中不同的變化。我們希望將復(fù)雜度保持在盡可能低的水平,最好避免超過 O(n)。

 

O(1)

這是理想的情況,無論有多少個項目,不管是一個還是一百萬個,完成的時間量都將保持不變。執(zhí)行單個操作的大多數(shù)操作都是 O(1)。把數(shù)據(jù)寫到數(shù)組、在特定索引處獲取項目、添加子元素等都將會花費相同的時間量,這與數(shù)組的長度無關(guān)。

 

  1. const a1 = performance.now(); 
  2. smArr.push(27); 
  3. const a2 = performance.now(); 
  4. console.log(`Time: ${a2 - a1}`); // Less than 1 Millisecond 
  5.  
  6.  
  7. const b1 = performance.now(); 
  8. bigArr.push(27); 
  9. const b2 = performance.now(); 
  10. console.log(`Time: ${b2 - b1}`); // Less than 1 Millisecond 

 

O(n)

在默認(rèn)情況下,所有的循環(huán)都是線性增長的,因為數(shù)據(jù)的大小和完成的時間之間存在一對一的關(guān)系。所以如果你有 1,000 個數(shù)組項,將會花費的 1,000 倍時間。

 

  1. const a1 = performance.now(); 
  2. smArr.forEach(item => console.log(item)); 
  3. const a2 = performance.now(); 
  4. console.log(`Time: ${a2 - a1}`); // 3 Milliseconds 
  5.  
  6. const b1 = performance.now(); 
  7. bigArr.forEach(item => console.log(item)); 
  8. const b2 = performance.now(); 
  9. console.log(`Time: ${b2 - b1}`); // 13 Milliseconds 

 

O(n^2)

指數(shù)增長是一個陷阱,我們都掉進去過。你是否需要為數(shù)組中的每個項目找到匹配對?將循環(huán)放入循環(huán)中是一種很好的方式,可以把 1000 個項目的數(shù)組變成一百萬個操作搜索,這將會使你的瀏覽器失去響應(yīng)。與使用雙重嵌套循環(huán)進行一百萬次操作相比,最好在兩個單獨的循環(huán)中進行 2,000 次操作。

 

  1. const a1 = performance.now(); 
  2. smArr.forEach(() => { 
  3.     arr2.forEach(item => console.log(item)); 
  4. }); 
  5. const a2 = performance.now(); 
  6. console.log(`Time: ${a2 - a1}`); // 8 Milliseconds 
  7.  
  8.  
  9. const b1 = performance.now(); 
  10. bigArr.forEach(() => { 
  11.     arr2.forEach(item => console.log(item)); 
  12. }); 
  13. const b2 = performance.now(); 
  14. console.log(`Time: ${b2 - b1}`); // 307 Milliseconds 

O(log n)

我認(rèn)為關(guān)于對數(shù)增長比較好的比喻,是想象在字典中查找像 “notation” 之類的單詞。你不會在一個詞條一個詞條的去進行搜索,而是先找到 “N” 這一部分,然后是 “OPQ” 這一頁,然后按字母順序搜索列表直到找到匹配項。

通過這種“分而治之”的方法,找到某些內(nèi)容的時間仍然會因字典的大小而改變,但遠不及 O(n) 。因為它會在不查看大部分?jǐn)?shù)據(jù)的情況下逐步搜索更具體的部分,所以搜索一千個項目可能需要少于 10 個操作,而一百萬個項目可能需要少于 20 個操作,這使你的效率最大化。

在這個例子中,我們可以做一個簡單的 快速排序。

 

  1. const sort = arr => { 
  2.   if (arr.length < 2) return arr; 
  3.  
  4.   let pivot = arr[0]; 
  5.   let left = []; 
  6.   let right = []; 
  7.  
  8.   for (let i = 1, total = arr.length; i < total; i++) { 
  9.     if (arr[i] < pivot) left.push(arr[i]); 
  10.     else right.push(arr[i]); 
  11.   }; 
  12.   return [ 
  13.     ...sort(left), 
  14.     pivot, 
  15.     ...sort(right
  16.   ]; 
  17. }; 
  18. sort(smArr); // 0 Milliseconds 
  19. sort(bigArr); // 1 Millisecond 

 

O(n!)

最糟糕的一種可能性是析因增長。最經(jīng)典的例子就是旅行的推銷員問題。如果你要在很多距離不同的城市之間旅行,如何找到在所有城市之間返回起點的最短路線?暴力方法將是檢查每個城市之間所有可能的路線距離,這是一個階乘并且很快就會失控。

由于這個問題很快會變得非常復(fù)雜,因此我們將通過簡短的遞歸函數(shù)演示這種復(fù)雜性。這個函數(shù)會將一個數(shù)字去乘以函數(shù)自己,然后將數(shù)字減去1。階乘中的每個數(shù)字都會這樣計算,直到為 0,并且每個遞歸層都會把其乘積添加到原始數(shù)字中。

階乘只是從 1 開始直至該數(shù)字的乘積。那么 6!是 1x2x3x4x5x6 = 720。

 

  1. const factorial = n => { 
  2.   let num = n; 
  3.  
  4.   if (n === 0) return 1 
  5.   for (let i = 0; i < n; i++) { 
  6.     num = n * factorial(n - 1); 
  7.   }; 
  8.  
  9.   return num; 
  10. }; 
  11. factorial(1); // 2 Milliseconds 
  12. factorial(5); // 3 Milliseconds 
  13. factorial(10); // 85 Milliseconds 
  14. factorial(12); //  11,942 Milliseconds 

 

我原本打算顯示 factorial(15),但是 12 以上的值都太多,并且使頁面崩潰了,這也證明了為什么需要避免這種情況。

結(jié)束語

我們需要編寫高性能的代碼似乎是一個不爭得事實,但是我敢肯定,幾乎每個開發(fā)人員都創(chuàng)建過至少兩重甚至三重嵌套循環(huán),因為“它確實有效”。Big O 表示法在表達和考慮復(fù)雜性方面是非常必要的,這是我們從未有過的方式。

責(zé)任編輯:華軒 來源: segmentfault
相關(guān)推薦

2021-01-05 10:41:42

算法時間空間

2024-04-25 08:33:25

算法時間復(fù)雜度空間復(fù)雜度

2020-06-01 08:42:11

JavaScript重構(gòu)函數(shù)

2019-11-18 12:41:35

算法Python計算復(fù)雜性理論

2021-06-28 06:15:14

算法Algorithm時間空間復(fù)雜度

2021-09-17 10:44:50

算法復(fù)雜度空間

2020-11-30 06:26:31

算法時間表示法

2022-08-05 14:23:08

機器學(xué)習(xí)計算復(fù)雜度算法

2009-07-09 10:45:16

C#基本概念復(fù)雜度遞歸與接口

2020-12-30 05:35:56

數(shù)據(jù)結(jié)構(gòu)算法

2022-02-13 20:04:04

鏈表節(jié)點代碼

2018-07-31 09:52:38

機器學(xué)習(xí)排序算法圖像處理

2015-10-13 09:43:43

復(fù)雜度核心

2018-12-18 10:11:37

軟件復(fù)雜度軟件系統(tǒng)軟件開發(fā)

2019-12-24 09:46:00

Linux設(shè)置密碼

2022-08-16 09:04:23

代碼圈圈復(fù)雜度節(jié)點

2020-12-30 09:20:27

代碼

2014-07-01 15:49:33

數(shù)據(jù)結(jié)構(gòu)

2021-07-29 11:30:54

遞歸算法

2021-10-15 09:43:12

希爾排序復(fù)雜度
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 欧美精品第一页 | 久久精品国产亚洲夜色av网站 | 国产成人久久精品一区二区三区 | 国产精品久久久乱弄 | 久草日韩 | 午夜影院| av一区在线观看 | 欧洲亚洲精品久久久久 | 91精品国产91久久久久久吃药 | 日本不卡一区二区三区 | 国产精品久久久久一区二区三区 | 在线观看三级av | 久久精品手机视频 | 国产精品久久久久久模特 | 国产日韩亚洲欧美 | www.亚洲区| 精品自拍视频在线观看 | 日本 欧美 国产 | 色婷婷亚洲国产女人的天堂 | 精品在线视频播放 | 午夜精品久久 | 日本不卡免费新一二三区 | 岛国毛片在线观看 | 91综合在线视频 | 成人av一区二区亚洲精 | 久久区二区 | 久久精品视频在线观看 | 日韩有码在线观看 | 龙珠z在线观看 | 国产亚洲精品一区二区三区 | 欧美另类视频 | 国产精品亚洲综合 | 日韩精品免费视频 | 欧美久久久久久久 | 亚洲一区二区在线视频 | 欧美日韩不卡在线 | www亚洲免费国内精品 | 久久99蜜桃综合影院免费观看 | 亚洲精品久久久久久宅男 | 日韩久久久久 | 久色激情 |