2020-4-28
時間複雜度與空間複雜度javascript
我儘可能用 最少的文字,最少的代碼。來說明白數據結構與算法。
const findCat = (n) => { // 定義變量 let name = '石興龍'; let animal = '貓'; let cat_number = 0 // n 越大,循環的次數越多 for (let i = 0; i < n; i++) { cat_number++; } console.log(`${name} 有 ${cat_number} 只貓`) } findCat(1) // 石興龍 有 1 只貓 findCat(10) // 石興龍 有 10 只貓 findCat(n) // 石興龍 有 n 只貓
先來看看執行過程。先定義了 3 個變量、其次 for 循環、最後一行打印。假設每一行的執行時間爲 x 。那麼總的執行時間爲:java
T(n) = 3x + for(n) + x算法
其中 3x 和 x 的執行時間是不會變的,和 n 沒有關係,咱們忽略不計。那麼如今的執行時間是:數組
T(n) = for(n) = O(n)數據結構
find 函數的複雜度徹底依賴變量 n 的大小,因此就是 O(n)dom
| 複雜度 | 執行速度 | | -- | --| | O(1) | 最快 | | O(logn) | 快 | | O(n) | 慢 | | O(nLong) | 很慢 | | O(n次方) | 最慢 |
// 最快的代碼 O(1) let findCat = () => { let name = '石興龍'; let animal = '貓'; let cat_number = 0 let n = 10 for (let i = 0; i < n; i++) { cat_number++; } console.log(`${name} 有 ${cat_number} 只貓`) } findCat() // 石興龍 有 10 只貓 // 雖然也有 for 循環,可是執行時間是固定的 // 快的代碼 O(logn) findCat = (n) => { let name = '石興龍'; let animal = '貓'; let cat_number = 0 for (let i = 0; i < n; i++) { if (i % 2 === 0) { cat_number++; } } console.log(`${name} 有 ${cat_number} 只貓`) } findCat(10) // 石興龍 有 5 只貓 // logn 函數產生的值 < n // 慢的代碼 O(n) findCat = (n) => { let name = '石興龍'; let animal = '貓'; let cat_number = 0 for (let i = 0; i < n; i++) { cat_number++; } console.log(`${name} 有 ${cat_number} 只貓`) } findCat(10) // 石興龍 有 10 只貓 // 執行的時間 和 n 成正比 // 很慢的代碼 O(nLong) findCat = (n) => { let name = '石興龍'; let animal = '貓'; let cat_number = 0 for (let i = 0; i < n;) { i += 0.5; cat_number += 1; } console.log(`${name} 有 ${cat_number} 只貓`) } findCat(10) // 石興龍 有 20 只貓 // logn 函數產生的值 > n // 最慢的代碼 O(n次方) findCat = (n) => { let name = '石興龍'; let animal = '貓'; let cat_number = 0 for (let i = 0; i < n; i++) { for (let j = 0; j < n; j++) { cat_number++; } } console.log(`${name} 有 ${cat_number} 只貓`) } findCat(10) // 石興龍 有 100 只貓 // for 循環的執行次數是 n 的平方,甚至更大
let cats = ['鋼蛋兒', '灰灰', '三花', '豆芽'] findCat = (catName) => { let name = '石興龍'; let animal = '貓'; let cat_number = 0 for (let i = 0; i < cats.length; i++) { if (cats[i] === catName) { console.log(`${catName} 排行第 ${i}`) break; } } console.log(`${catName} 不是你的貓`) } findCat('鋼蛋兒') // 鋼蛋兒 排行第 1 // 執行效率最快 O(1) findCat('豆芽') // 豆芽 排行第 4 // 執行效率最慢 O(n) findCat(parseInt(Math.random() * cats.length)) // 平均執行效率爲 O(n),由於是隨機的
// 插入貓,擴容數組 let index = 4 let insertCat = (newCatName) => { if (index === cats.length) { let newCats = [] for (let i = 0; i < cats.length; i++) { newCats.push(cats[i]) } cats = newCats } index++; cats.push(newCatName) } insertCat('金漸層') // 複雜度:O(n) insertCat('海雙布偶') // 複雜度:O(1) insertCat('藍白高地') // 複雜度:O(1) /* 均攤:雖然有循環,可是循環是有規律的。 每一次 O(n) 的後面都跟着 n - 1 次 O(1) */