天天看點

【化解資料結構】從這裡開啟資料結構和算法

【化解資料結構】從這裡開啟資料結構和算法

大家好,我是小丞同學,一名大二的前端愛好者

這篇文章是資料結構與算法專欄的第一篇博文

非常感謝你的閱讀,不對的地方歡迎指正

願你忠于自己,熱愛生活

知識點搶先看

算法基礎

計算時間複雜度

計算空間複雜度

資料結構和算法的學習指南

文末有驚喜噢~

專欄簡介

按照慣例,每個專欄的第一篇文章都會簡單的介紹一下這個專欄的内容,以及未來的更文計劃

本專欄 【化解資料結構】,将在這裡總結自己學習資料結構和算法的學習筆記,從這篇算法入門開始,未來更文将涉及棧、隊列、連結清單、堆、樹、圖…等資料結構,以及經典排序算法,算法設計思想等進階算法…,同時将會結合 LeetCode 題目對每篇文章進行鞏固和提升,歡迎大家關注本專欄或添加作者本文聯系方式,一起努力,一起刷題,一起進步

【化解資料結構】從這裡開啟資料結構和算法

(圖檔來源于慕課網截圖)

引言

在正式寫這個之前,先來講講為什麼要學資料結構和算法?

為了計算出最優解

這是我的答案,當我打開 LeetCode 第一題兩數之和的送出記錄時,我發現自己半年前的代碼,耗時 240ms,記憶體占用 40多mb 時,我感受到了它的魅力

【化解資料結構】從這裡開啟資料結構和算法

在最新的代碼中,我采用了 map 的容器,通過 has 方法替代了先前采用的 indexof 方法,從查到的資料來看,map 的查找的時間複雜度為 O(1) ,indexOf 為 O(n) ,在 map 的底層實作中采用了哈希表的資料結構,極大的優化了查找的複雜度

接下來我們來看看如何計算時間、空間複雜度!

一. 大 O 表示法

關于複雜度的計算,我們采用的是 大 O 表示法 ,它用來描述算法性能和複雜程度

常見的表示

符号大O标記法 名稱

O(1) 常數

O(log N) 對數

O(N) 線性

O(N log N) 對數多項式

O(N^2) 二次

O(2^N) 指數

O(N!) 階乘

大 O 表示法一般考慮的是 CPU 占用時間,它可以粗略的了解代碼運作的時間效率

例如

function test(num){
    return ++num;
}      

我們調用這個函數一次,執行時間是 t ,我們再調用一次,執行時間還是 t,和傳入的參數無關, test 函數的性能都一樣,是以它的複雜度為 O(1)

當循環 n 次時,就是 O(n)

二. 時間複雜度

大 O 表示法表明的是該段代碼執行時間随資料規模增大的變化趨勢,它的特點是

隻關注量級最大的時間複雜度

常見的時間複雜度量級 O(1) < O(logn) < O(n) < O(n^2)

對于 O(2)、O(3) 這些,我們都叫做 O(1) 常數級

例如:

1. O(1)

let i = 0;
i += 1;
// 每次執行代碼隻執行一次 O(1)      

這段代碼每次隻執行一次,是以為 O(1)

2. O(n)

for (let j = 0; j < n; j++) {
    console.log(j);
}      

再上面這段代碼中,我們每次都需要執行 n 次的 log ,是以我們可以把它看作 O(n)

同樣的我們再來看一個

let i = 0;
i += 1;
for (let j = 0; j < navigator; j++) {
    console.log(j);
}      

這種代碼我們經常寫,前面是我們剛剛計算的 O(1),後面是 O(n) ,它們并行排列,時間複雜度相加,取最大的那個

是以它的時間複雜度同樣是 O(n)

3. O(log(n))

while (i < n) {
    console.log(i);
    i *= 2;
}      

對于 log(n) 的情況,在個時間複雜度是很好的,當然 O(1) 是最好的,但是在解題的時候,如果能優化到 log(n) 也是很不錯的了

那它是如何計算的呢?

我們可以看到,這裡采用了 變量i來控制循環的終止,每次循環體中,都需要 2 * i 的操作

是以對于時間複雜度的計算 2^t = n 解得 t = log(n)

4. O(n^2)

for (let i = 0; i < n; i++) {
    for (let j = 0; j < n; j++) {
        console.log(i);
    }
}      

對于這種嵌套排列,時間複雜度是 n^2 ,外面一層 n ,裡面一層 n 乘一下就是 n^2,冒泡排序的時間複雜度就是 O(n^2)

關于時間複雜度就介紹這麼多,其他的思路都差不多

【化解資料結構】從這裡開啟資料結構和算法

三、空間複雜度

空間複雜度表示的是:存儲空間随資料規模的增長趨勢,在 LeetCode 中最直接的反應就是記憶體消耗

let i = 0;      

在這裡我們申請了單個變量的記憶體空間,為 O(1)

let arr = []
for(let i = 0;i < n;i++) {
    arr.push(i)
}      

像這樣的一個數組,并給它填滿值,n 越大,它需要配置設定的空間就越多,它的空間複雜度就是 O(n)

3. O(n^2)

int arr = [][]// 周遊指派      

聲明一個二維數組,填滿值,它的空間複雜度就是 O(n^2) ,你可以了解為一個矩陣,n*n 為 n^2

總結

複雜度計算按最高階來計算

時間、空間複雜度描述的都是随資料規模的變化趨勢

時間複雜度的重點在于循環嵌套

空間複雜度關注于記憶體

繼續閱讀