我是如何學習數據結構與算法的?

數據結構與算法的地位對於一個程序員來講不言而喻。今天這篇文章不是來勸大家學習數據結構與算法的,也不是來和大家說數據結構與算法有多重要。
主要是最近幾天後臺有讀者問我是如何學習數據結構與算法的,有沒有什麼捷徑,是要看視頻仍是看書,去哪刷題等…..並且有些仍是大三大四的,搞的我都替大家着急、擔憂…..
因此我今天就分享下本身平時都是怎麼學習的。vue

學習算法的捷徑就是多刷題

說實話,要說捷徑,我以爲就是腳踏實地着多動手去刷題,多刷題。
可是,若是你是小白,也就是說,你連常見的數據結構,如鏈表、樹以及常見的算法思想,如遞歸、枚舉、動態規劃這些都沒學過,那麼,我不建議你去刷題的。而是先去找本書先去學習這些,而後再去刷題。程序員

也就是說,假如你要去諸如leetcode這些網站刷題,那麼,你要先具有必定的基礎,這些基礎包括:
一、常見數據結構:鏈表、樹(如二叉樹)。
二、常見算法思想:貪婪法、分治法、窮舉法、動態規劃,回溯法。
以上列出來的算是最基本的吧。就是說你刷題以前,要把這些過一遍再去刷題。若是你連這些最基本的都不知道的話,那麼你再刷題的過程當中,會很難受的,思路也會相對比較少。
總之,千萬不要急,先把這些基本的過一遍,力求理解,再去刷題。這些基礎的數據結構與算法,我是在大一第二學期學的,我沒看視頻,我是經過看書學的,那時候看的書是:
一、算法分析與分析基礎:這本比較簡單,推薦新手看。
二、數據結構與算法分析—-C語言描述:代碼用C寫的,推薦看。
三、挑戰程序設計競賽(第二版):也是很不錯的一本書,推薦看。
具體能夠看個人另一篇文章,裏面是介紹這幾本書的:
算法與數據結構書籍與視頻福利算法

說實話,我那一學期的時間幾乎都花在數據結構與算法上,但刷的題不多,只是書本上的一些例題。因此當我把這些基本的過一遍以後,再去一些網站刷題依舊很是菜。
因此大家千萬別期望覺得本身把這些思想學完以後刷題會很牛,只有多刷題,只有多動手實踐,你的靈敏度纔會提升起來。
在這裏說一下前陣子有個很是火爆的專欄—-【數據結構與算法之美】markdown

我沒買這個專欄,我想說的是,買了就必定要去看,千萬別浪費。也千萬不要以爲學完這個專欄你就會變的多牛逼,若是你只是跟着進度去學習這個專欄,本身沒有花時間去刷題、去動手時間。那我能夠保證,你學完以後仍是那麼菜。
總結下:
提升數據結構與算法沒啥捷徑,最好的捷徑就是多刷題。可是,刷題的前提是你要先學會一些基本的數據結構與算法思想。網絡

追求完美

如何刷題?如何對待一道算法題?
我以爲,在作題的時候,必定要追求完美,千萬不要把一道題作出來以後,提交經過,而後就趕忙下一道。
算法能力的提高和作題的數量是有必定的關係,但並非線性關係。也就是說,在作題的時候,要力求一題多解,若是本身實在想不出來其餘辦法了,能夠去看看別人是怎麼作的,千萬不要以爲模仿別人的作法是件丟人的事。
我作題的時候,我一看到一道題,可能第一想法就是用很粗糙的方式作,由於不少題採用暴力法都會很容易作,就是時間複雜度很高。以後,我就會慢慢思考,看看有沒其餘方法來下降時間複雜度或空間複雜度。最後,我會去看一下別人的作法,固然,並非每道題都會這樣執行。
衡量一道算法題的好壞無非就是時間複雜度空間複雜度,因此咱們要力求完美,就要把這兩個降到最低,令他們相輔相成。
我舉道例題吧:
問題: 一隻青蛙一次能夠跳上1級臺階,也能夠跳上2級。求該青蛙跳上一個n級的臺階總共有多少種跳法?
這道題我在之前的分章分析過,不懂的能夠先看下以前寫的:遞歸與動態規劃—-基礎篇1數據結構

方法1::暴力遞歸
這道題不難,或許你會採起下面的作法:app

public static int solve(int n){
    if(n == 1 || n == 2){
        return n;
    }else if(n <= 0){
        return 0;
    }else{
        return solve(n-1) + solve(n-2);
    }
}

這種作法的時間複雜度很高,指數級別了。可是若是你提交以後僥倖經過了,而後你就接着下一道題了,那麼你就要好好想一想了。
方法二:空間換時間
力求完美,咱們能夠考慮用空間換時間:這道題如何你去仔細想想,會發現有不少是重複執行了。因此能夠採起下面的方法:學習

//用一個HashMap來保存已經計算過的狀態
static Map<Integer,Integer> map = new HashMap();
public static int solve(int n){
    if(n <= 0)return 0;
    else if(n <= 2){
        return n;
    }else{//是否計算過
        if(map.containsKey(n)){
            return map.get(n);
        }else{
            int m = solve(n-1) + solve(n-2);
            map.put(n, m);
            return m;
        }
    }
}

這樣,能夠大大縮短期。也就是說,當一道題你作了以後,發現時間複雜度很高,那麼能夠考慮下,是否有更好的方法,是否能夠用空間換時間。優化

方法三:斐波那契數列
實際上,咱們能夠把空間複雜度弄的更小,不須要HashMap來保存狀態:網站

public static int solve(int n){
    if(n <= 0)
       return 0;
    if(n <= 2){
        return n;
    }

    int f1 = 0;
    int f2 = 1;
    int sum = 0;
    for(int i = 1; i<= n; i++){
        sum = f1 + f2;
        f1 = f2;
        f2 = sum;
    }
    return sum;
}

我弄這道題給大家看,並非在教大家這道題怎麼作,而是有如下目的:
一、在刷題的時候,咱們要力求完美。
二、我想不到這些方法啊,怎麼辦?那麼你就能夠去看別人的作法,以後,遇到相似的題,你就會更有思路,更知道往哪一個方向想。
三、能夠從簡單暴力入手作一道題,在考慮空間與時間之間的衡量,一點點去優化。

推薦一些刷題網站

我通常是在leetcode和牛客網刷題,感受挺不錯,題目難度不是很大。
在牛客網那裏,我主要刷劍指Offer,不過那裏也有個在線刷leetcode,不過裏面的題量比較少。牛客網刷題有個很是方便的地方就是有個討論區,那裏會有不少大佬分享他們的解題方法,不用咱們去百度找題解。因此你作完後,實在想不出,能夠很方便着去看別人是怎麼作的。
至於leetcode,也是大部分題目官方都有給出答案,也是個不錯的刷題網站。大家能夠兩個挑選一個,或者兩個都刷。
固然,還有其餘刷題的網站,不過,其餘網站沒刷過,不大清除如何。

再說數據結構

前面我主要是說了我平時都是怎麼學習算法的。在數據結構方法,我只是列舉了大家必定要學習鏈表樹(二叉堆),但這是最基本的,刷題以前要掌握的,對於數據結構,我列舉下一些比較重要的:
一、鏈表(如單向鏈表、雙向鏈表)。
二、樹(如二叉樹、平衡樹、紅黑樹)。
三、圖(如最短路徑的幾種算法)。
四、隊列、棧、矩陣。
對於這些,本身必定要動手實現一遍。你能夠看書,也能夠看視頻,新手能夠先看視頻,不過前期能夠看視頻,以後我建議是必定要看書。
視頻和書我之前有推薦過:
算法與數據結構書籍與視頻福利
例如對於平衡樹,可能你跟着書本的代碼實現以後,過陣子你就忘記,不過這沒關係,雖然你忘記了,可是若是你以前用代碼實現過,理解過,那麼當你再次看到的時候,會很快就記起來,很快就知道思路,並且你的抽象能力等等會在不知不覺中提高起來。以後再學習紅黑樹啊,什麼數據結構啊,都會學的很快。

最最重要

動手去作,動手去作,動手去作。重要的話說三遍。
千萬不要找了一堆資源,訂好了學習計劃,我要留到某某天就來去作…..
千萬不要這樣,而是當你激情來的時候,就立刻去幹,千萬不要留到某個放假日啊什麼鬼了,不少這種想法的人,最後會啥也沒作的。
也不要以爲要學習的有好多啊,不知道從哪學習起。我上面說了,能夠先學習最基本的,而後刷題,刷題是一個須要長期堅持的事情,一年,兩年。在刷題的過程當中,能夠穿插和學習其餘數據結構。

最後

今天就說這麼多,以上主要是我本身的學習方法,但願對你有所幫助。
對了,我好久以前就建過一個交流羣,不過該羣仍是挺安靜的,我也不多提到,若是你想加入,公衆號右下方有加入方式。你有什麼問題,能夠在羣裏提問,我看到的話,會盡可能解答。
最後說下我這個公衆號(苦逼的碼農),我主要寫【計算機網絡】、【數據結構與算法】、【Java】。通常90%都會是原創的,偶爾有些轉載的文章,只會比我本身寫的文章更好。
通常我會一陣子更新這個模塊、一陣子更新另外一個模塊的方式來寫文章。
若是你以爲有幫助,能夠分享給更多的朋友哦,這即是對我最大的支持 。

本公衆號(苦逼的碼農)專一於寫【Java】、【計算機網絡】、【數據結構與算法】,期待你加入交流。

相關文章
相關標籤/搜索