用JS怎樣學(xué)習(xí)算法復(fù)雜度?算法復(fù)雜度如何理解?
Admin 2021-10-09 群英技術(shù)資訊 933 次瀏覽
今天主要給大家分享用JS怎樣學(xué)習(xí)算法復(fù)雜度的內(nèi)容,一些朋友可能對(duì)于算法復(fù)雜度不是很了解,對(duì)此本文就給大家來介紹一下算法復(fù)雜度,下文代碼有一定的參考價(jià)值,需要的朋友可以看一看。
在本文中,我們將探討 “二次方” 和 “n log(n)” 等術(shù)語在算法中的含義。
在后面的例子中,我將引用這兩個(gè)數(shù)組,一個(gè)包含 5 個(gè)元素,另一個(gè)包含 50 個(gè)元素。我還會(huì)用到JavaScript中方便的performance API來衡量執(zhí)行時(shí)間的差異。
const smArr = [5, 3, 2, 35, 2]; 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 表示法是用來表示隨著數(shù)據(jù)集的增加,計(jì)算任務(wù)難度總體增長的一種方式。盡管還有其他表示法,但通常 big O 表示法是最常用的,因?yàn)樗塾谧顗牡那闆r,更容易量化和考慮。最壞的情況意味著完成任務(wù)需要最多的操作次數(shù);如果你在一秒鐘內(nèi)就能恢復(fù)打亂魔方,那么你只擰了一圈的話,不能說自己是做得最好的。
當(dāng)你進(jìn)一步了解算法時(shí),就會(huì)發(fā)現(xiàn)這非常有用,因?yàn)樵诶斫膺@種關(guān)系的同時(shí)去編寫代碼,就能知道時(shí)間都花在了什么地方。
當(dāng)你了解更多有關(guān) Big O 表示法的信息時(shí),可能會(huì)看到下圖中不同的變化。我們希望將復(fù)雜度保持在盡可能低的水平,最好避免超過 O(n)。

這是理想的情況,無論有多少個(gè)項(xiàng)目,不管是一個(gè)還是一百萬個(gè),完成的時(shí)間量都將保持不變。執(zhí)行單個(gè)操作的大多數(shù)操作都是 O(1)。把數(shù)據(jù)寫到數(shù)組、在特定索引處獲取項(xiàng)目、添加子元素等都將會(huì)花費(fèi)相同的時(shí)間量,這與數(shù)組的長度無關(guān)。
const a1 = performance.now();
smArr.push(27);
const a2 = performance.now();
console.log(`Time: ${a2 - a1}`); // Less than 1 Millisecond
const b1 = performance.now();
bigArr.push(27);
const b2 = performance.now();
console.log(`Time: ${b2 - b1}`); // Less than 1 Millisecond
在默認(rèn)情況下,所有的循環(huán)都是線性增長的,因?yàn)閿?shù)據(jù)的大小和完成的時(shí)間之間存在一對(duì)一的關(guān)系。所以如果你有 1,000 個(gè)數(shù)組項(xiàng),將會(huì)花費(fèi)的 1,000 倍時(shí)間。
const a1 = performance.now();
smArr.forEach(item => console.log(item));
const a2 = performance.now();
console.log(`Time: ${a2 - a1}`); // 3 Milliseconds
const b1 = performance.now();
bigArr.forEach(item => console.log(item));
const b2 = performance.now();
console.log(`Time: ${b2 - b1}`); // 13 Milliseconds
指數(shù)增長是一個(gè)陷阱,我們都掉進(jìn)去過。你是否需要為數(shù)組中的每個(gè)項(xiàng)目找到匹配對(duì)?將循環(huán)放入循環(huán)中是一種很好的方式,可以把 1000 個(gè)項(xiàng)目的數(shù)組變成一百萬個(gè)操作搜索,這將會(huì)使你的瀏覽器失去響應(yīng)。與使用雙重嵌套循環(huán)進(jìn)行一百萬次操作相比,最好在兩個(gè)單獨(dú)的循環(huán)中進(jìn)行 2,000 次操作。
const a1 = performance.now();
smArr.forEach(() => {
arr2.forEach(item => console.log(item));
});
const a2 = performance.now();
console.log(`Time: ${a2 - a1}`); // 8 Milliseconds
const b1 = performance.now();
bigArr.forEach(() => {
arr2.forEach(item => console.log(item));
});
const b2 = performance.now();
console.log(`Time: ${b2 - b1}`); // 307 Milliseconds
我認(rèn)為關(guān)于對(duì)數(shù)增長最好的比喻,是想象在字典中查找像 “notation” 之類的單詞。你不會(huì)在一個(gè)詞條一個(gè)詞條的去進(jìn)行搜索,而是先找到 “N” 這一部分,然后是 “OPQ” 這一頁,然后按字母順序搜索列表直到找到匹配項(xiàng)。
通過這種“分而治之”的方法,找到某些內(nèi)容的時(shí)間仍然會(huì)因字典的大小而改變,但遠(yuǎn)不及 O(n) 。因?yàn)樗鼤?huì)在不查看大部分?jǐn)?shù)據(jù)的情況下逐步搜索更具體的部分,所以搜索一千個(gè)項(xiàng)目可能需要少于 10 個(gè)操作,而一百萬個(gè)項(xiàng)目可能需要少于 20 個(gè)操作,這使你的效率最大化。
在這個(gè)例子中,我們可以做一個(gè)簡單的快速排序。
const sort = arr => {
if (arr.length < 2) return arr;
let pivot = arr[0];
let left = [];
let right = [];
for (let i = 1, total = arr.length; i < total; i++) {
if (arr[i] < pivot) left.push(arr[i]);
else right.push(arr[i]);
};
return [
...sort(left),
pivot,
...sort(right)
];
};
sort(smArr); // 0 Milliseconds
sort(bigArr); // 1 Millisecond
最糟糕的一種可能性是析因增長。最經(jīng)典的例子就是旅行的推銷員問題。如果你要在很多距離不同的城市之間旅行,如何找到在所有城市之間返回起點(diǎn)的最短路線?暴力方法將是檢查每個(gè)城市之間所有可能的路線距離,這是一個(gè)階乘并且很快就會(huì)失控。
由于這個(gè)問題很快會(huì)變得非常復(fù)雜,因此我們將通過簡短的遞歸函數(shù)演示這種復(fù)雜性。這個(gè)函數(shù)會(huì)將一個(gè)數(shù)字去乘以函數(shù)自己,然后將數(shù)字減去1。階乘中的每個(gè)數(shù)字都會(huì)這樣計(jì)算,直到為 0,并且每個(gè)遞歸層都會(huì)把其乘積添加到原始數(shù)字中。
階乘只是從 1 開始直至該數(shù)字的乘積。那么6!是1x2x3x4x5x6 = 720。
const factorial = n => {
let num = n;
if (n === 0) return 1
for (let i = 0; i < n; i++) {
num = n * factorial(n - 1);
};
return num;
};
factorial(1); // 2 Milliseconds
factorial(5); // 3 Milliseconds
factorial(10); // 85 Milliseconds
factorial(12); // 11,942 Milliseconds
我原本打算顯示factorial(15),但是 12 以上的值都太多,并且使頁面崩潰了,這也證明了為什么需要避免這種情況。
我們需要編寫高性能的代碼似乎是一個(gè)不爭得事實(shí),但是我敢肯定,幾乎每個(gè)開發(fā)人員都創(chuàng)建過至少兩重甚至三重嵌套循環(huán),因?yàn)椤八_實(shí)有效”。Big O 表示法在表達(dá)和考慮復(fù)雜性方面是非常必要的,這是我們從未有過的方式。
以上就是關(guān)于JS學(xué)習(xí)算法復(fù)雜度的介紹啦,感興趣的朋友可以了解看看,希望對(duì)大家學(xué)習(xí)算法復(fù)雜度有幫助,想要了解更多算法復(fù)雜度的內(nèi)容,大家可以繼續(xù)瀏覽群英網(wǎng)絡(luò)其他相關(guān)的文章。
文本轉(zhuǎn)載自腳本之家
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:[email protected]進(jìn)行舉報(bào),并提供相關(guān)證據(jù),查實(shí)之后,將立刻刪除涉嫌侵權(quán)內(nèi)容。
猜你喜歡
本篇文章介紹了我在開發(fā)過程中發(fā)現(xiàn)的一個(gè)小問題,就是node.js如何能夠根據(jù)不同的請(qǐng)求路徑來返回得到不同數(shù)據(jù),通讀本篇對(duì)大家的學(xué)習(xí)或工作具有一定的價(jià)值,需要的朋友可以參考下
本篇文章帶大家繼續(xù)angular的學(xué)習(xí),簡單了解一下angular中Directive指令的使用,希望對(duì)大家有所幫助!
這篇文章主要介紹了解決elementui表格操作列自適應(yīng)列寬,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
setState作為react中的重要部分,將對(duì)組件 state 的更改排入隊(duì)列,并通知 React 需要使用更新后的 state 重新渲染此組件及其子組件。下面本篇文章帶大家了解一下React中的setState機(jī)制,希望對(duì)大家有所幫助!
JS自帶一套內(nèi)存管理引擎,負(fù)責(zé)創(chuàng)建對(duì)象、銷毀對(duì)象,以及垃圾回收,下面這篇文章主要給大家介紹了關(guān)于JavaScript垃圾回收機(jī)制的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
推薦內(nèi)容
相關(guān)標(biāo)簽
成為群英會(huì)員,開啟智能安全云計(jì)算之旅
立即注冊(cè)關(guān)注或聯(lián)系群英網(wǎng)絡(luò)
7x24小時(shí)售前:400-678-4567
7x24小時(shí)售后:0668-2555666
24小時(shí)QQ客服
群英微信公眾號(hào)
CNNIC域名投訴舉報(bào)處理平臺(tái)
服務(wù)電話:010-58813000
服務(wù)郵箱:[email protected]
投訴與建議:0668-2555555
Copyright ? QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版權(quán)所有
增值電信經(jīng)營許可證 : B1.B2-20140078 ICP核準(zhǔn)(ICP備案)粵ICP備09006778號(hào) 域名注冊(cè)商資質(zhì) 粵 D3.1-20240008