一個(gè)熱愛(ài)編程的在校生,我的世界不只有coding,還有writing。目前維護(hù)訂閱號(hào)「苦逼的碼農(nóng)」,專注于寫(xiě)「算法與數(shù)據(jù)結(jié)構(gòu)」,「Java」,「計(jì)算機(jī)網(wǎng)絡(luò)」。
數(shù)據(jù)結(jié)構(gòu)與算法的地位對(duì)于一個(gè)程序員來(lái)說(shuō)不言而喻。今天這篇文章不是來(lái)勸你們學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算法的,也不是來(lái)和你們說(shuō)數(shù)據(jù)結(jié)構(gòu)與算法有多重要。
主要是最近幾天后臺(tái)有讀者問(wèn)我是如何學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算法的,有沒(méi)有什么捷徑,是要看視頻還是看書(shū),去哪刷題等…..而且有些還是大三大四的,搞的我都替你們著急、擔(dān)心…..
所以我今天就分享下自己平時(shí)都是怎么學(xué)習(xí)的。
學(xué)習(xí)算法的捷徑就是多刷題
說(shuō)實(shí)話,要說(shuō)捷徑,我覺(jué)得就是腳踏實(shí)地著多動(dòng)手去刷題,多刷題。
但是,如果你是小白,也就是說(shuō),你連常見(jiàn)的數(shù)據(jù)結(jié)構(gòu),如鏈表、樹(shù)以及常見(jiàn)的算法思想,如遞歸、枚舉、動(dòng)態(tài)規(guī)劃這些都沒(méi)學(xué)過(guò),那么,我不建議你去刷題的。而是先去找本書(shū)先去學(xué)習(xí)這些,然后再去刷題。
也就是說(shuō),假如你要去諸如leetcode這些網(wǎng)站刷題,那么,你要先具備一定的基礎(chǔ),這些基礎(chǔ)包括:
1、常見(jiàn)數(shù)據(jù)結(jié)構(gòu):鏈表、樹(shù)(如二叉樹(shù))。
2、常見(jiàn)算法思想:貪婪法、分治法、窮舉法、動(dòng)態(tài)規(guī)劃,回溯法。
以上列出來(lái)的算是最基本的吧。就是說(shuō)你刷題之前,要把這些過(guò)一遍再去刷題。如果你連這些最基本的都不知道的話,那么你再刷題的過(guò)程中,會(huì)很難受的,思路也會(huì)相對(duì)比較少。
總之,千萬(wàn)不要急,先把這些基本的過(guò)一遍,力求理解,再去刷題。這些基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu)與算法,我是在大一第二學(xué)期學(xué)的,我沒(méi)看視頻,我是通過(guò)看書(shū)學(xué)的,那時(shí)候看的書(shū)是:
1、算法分析與分析基礎(chǔ):這本比較簡(jiǎn)單,推薦新手看。
2、數(shù)據(jù)結(jié)構(gòu)與算法分析—-C語(yǔ)言描述:代碼用C寫(xiě)的,推薦看。
3、挑戰(zhàn)程序設(shè)計(jì)競(jìng)賽(第二版):也是很不錯(cuò)的一本書(shū),推薦看。
具體可以看我的另外一篇文章,里面是介紹這幾本書(shū)的:算法與數(shù)據(jù)結(jié)構(gòu)書(shū)籍與視頻福利
說(shuō)實(shí)話,我那一學(xué)期的時(shí)間幾乎都花在數(shù)據(jù)結(jié)構(gòu)與算法上,但刷的題很少,只是書(shū)本上的一些例題。所以當(dāng)我把這些基本的過(guò)一遍之后,再去一些網(wǎng)站刷題依舊非常菜。
所以你們千萬(wàn)別指望以為自己把這些思想學(xué)完之后刷題會(huì)很牛,只有多刷題,只有多動(dòng)手實(shí)踐,你的靈敏度才會(huì)提高起來(lái)。
在這里說(shuō)一下前陣子有個(gè)非?;鸨膶凇?【數(shù)據(jù)結(jié)構(gòu)與算法之美】
我沒(méi)買(mǎi)這個(gè)專欄,我想說(shuō)的是,買(mǎi)了就一定要去看,千萬(wàn)別浪費(fèi)。也千萬(wàn)不要覺(jué)得學(xué)完這個(gè)專欄你就會(huì)變的多牛逼,如果你只是跟著進(jìn)度去學(xué)習(xí)這個(gè)專欄,自己沒(méi)有花時(shí)間去刷題、去動(dòng)手時(shí)間。那我可以保證,你學(xué)完之后還是那么菜。
總結(jié)下:
提高數(shù)據(jù)結(jié)構(gòu)與算法沒(méi)啥捷徑,最好的捷徑就是多刷題。但是,刷題的前提是你要先學(xué)會(huì)一些基本的數(shù)據(jù)結(jié)構(gòu)與算法思想。
追求完美
如何刷題?如何對(duì)待一道算法題?
我覺(jué)得,在做題的時(shí)候,一定要追求完美,千萬(wàn)不要把一道題做出來(lái)之后,提交通過(guò),然后就趕緊下一道。
算法能力的提升和做題的數(shù)量是有一定的關(guān)系,但并不是線性關(guān)系。也就是說(shuō),在做題的時(shí)候,要力求一題多解,如果自己實(shí)在想不出來(lái)其他辦法了,可以去看看別人是怎么做的,千萬(wàn)不要覺(jué)得模仿別人的做法是件丟人的事。
我做題的時(shí)候,我一看到一道題,可能第一想法就是用很粗糙的方式做,因?yàn)楹芏囝}采用暴力法都會(huì)很容易做,就是時(shí)間復(fù)雜度很高。之后,我就會(huì)慢慢思考,看看有沒(méi)其他方法來(lái)降低時(shí)間復(fù)雜度或空間復(fù)雜度。最后,我會(huì)去看一下別人的做法,當(dāng)然,并不是每道題都會(huì)這樣執(zhí)行。
衡量一道算法題的好壞無(wú)非就是時(shí)間復(fù)雜度和空間復(fù)雜度,所以我們要力求完美,就要把這兩個(gè)降到最低,令他們相輔相成。
我舉道例題吧:
問(wèn)題:一只青蛙一次可以跳上1級(jí)臺(tái)階,也可以跳上2級(jí)。求該青蛙跳上一個(gè)n級(jí)的臺(tái)階總共有多少種跳法?
這道題我在以前的分章分析過(guò),不懂的可以先看下之前寫(xiě)的:遞歸與動(dòng)態(tài)規(guī)劃---基礎(chǔ)篇1
方法1::暴力遞歸
這道題不難,或許你會(huì)采取下面的做法:
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); ? ?}}
這種做法的時(shí)間復(fù)雜度很高,指數(shù)級(jí)別了。但是如果你提交之后僥幸通過(guò)了,然后你就接著下一道題了,那么你就要好好想想了。
方法二:空間換時(shí)間
力求完美,我們可以考慮用空間換時(shí)間:這道題如何你去仔細(xì)想一想,會(huì)發(fā)現(xiàn)有很多是重復(fù)執(zhí)行了。所以可以采取下面的方法:
//用一個(gè)HashMap來(lái)保存已經(jīng)計(jì)算過(guò)的狀態(tài)static Map
這樣,可以大大縮短時(shí)間。也就是說(shuō),當(dāng)一道題你做了之后,發(fā)現(xiàn)時(shí)間復(fù)雜度很高,那么可以考慮下,是否有更好的方法,是否可以用空間換時(shí)間。
方法三:斐波那契數(shù)列
實(shí)際上,我們可以把空間復(fù)雜度弄的更小,不需要HashMap來(lái)保存狀態(tài):
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;}
我弄這道題給你們看,并不是在教你們這道題怎么做,而是有以下目的:
1、在刷題的時(shí)候,我們要力求完美。
2、我想不到這些方法啊,怎么辦?那么你就可以去看別人的做法,之后,遇到類似的題,你就會(huì)更有思路,更知道往哪個(gè)方向想。
3、可以從簡(jiǎn)單暴力入手做一道題,在考慮空間與時(shí)間之間的衡量,一點(diǎn)點(diǎn)去優(yōu)化。
推薦一些刷題網(wǎng)站
我一般是在leetcode和??途W(wǎng)刷題,感覺(jué)挺不錯(cuò),題目難度不是很大。
在牛客網(wǎng)那里,我主要刷劍指Offer,不過(guò)那里也有個(gè)在線刷leetcode,不過(guò)里面的題量比較少。牛客網(wǎng)刷題有個(gè)非常方便的地方就是有個(gè)討論區(qū),那里會(huì)有很多大佬分享他們的解題方法,不用我們?nèi)グ俣日翌}解。所以你做完后,實(shí)在想不出,可以很方便著去看別人是怎么做的。
至于leetcode,也是大部分題目官方都有給出答案,也是個(gè)不錯(cuò)的刷題網(wǎng)站。你們可以兩個(gè)挑選一個(gè),或者兩個(gè)都刷。
當(dāng)然,還有其他刷題的網(wǎng)站,不過(guò),其他網(wǎng)站沒(méi)刷過(guò),不大清除如何。
再說(shuō)數(shù)據(jù)結(jié)構(gòu)
前面我主要是說(shuō)了我平時(shí)都是怎么學(xué)習(xí)算法的。在數(shù)據(jù)結(jié)構(gòu)方法,我只是列舉了你們一定要學(xué)習(xí)鏈表和樹(shù)(二叉堆),但這是最基本的,刷題之前要掌握的,對(duì)于數(shù)據(jù)結(jié)構(gòu),我列舉下一些比較重要的:
1、鏈表(如單向鏈表、雙向鏈表)。
2、樹(shù)(如二叉樹(shù)、平衡樹(shù)、紅黑樹(shù))。
3、圖(如最短路徑的幾種算法)。
4、隊(duì)列、棧、矩陣。
對(duì)于這些,自己一定要?jiǎng)邮謱?shí)現(xiàn)一遍。你可以看書(shū),也可以看視頻,新手可以先看視頻,不過(guò)前期可以看視頻,之后我建議是一定要看書(shū)。
視頻和書(shū)我以前有推薦過(guò):算法與數(shù)據(jù)結(jié)構(gòu)書(shū)籍與視頻福利
例如對(duì)于平衡樹(shù),可能你跟著書(shū)本的代碼實(shí)現(xiàn)之后,過(guò)陣子你就忘記,不過(guò)這不要緊,雖然你忘記了,但是如果你之前用代碼實(shí)現(xiàn)過(guò),理解過(guò),那么當(dāng)你再次看到的時(shí)候,會(huì)很快就記起來(lái),很快就知道思路,而且你的抽象能力等等會(huì)在不知不覺(jué)中提升起來(lái)。之后再學(xué)習(xí)紅黑樹(shù)啊,什么數(shù)據(jù)結(jié)構(gòu)啊,都會(huì)學(xué)的很快。
最最重要
動(dòng)手去做,動(dòng)手去做,動(dòng)手去做。重要的話說(shuō)三遍。
千萬(wàn)不要找了一堆資源,訂好了學(xué)習(xí)計(jì)劃,我要留到某某天就來(lái)去做…..
千萬(wàn)不要這樣,而是當(dāng)你激情來(lái)的時(shí)候,就馬上去干,千萬(wàn)不要留到某個(gè)放假日啊什么鬼了,很多這種想法的人,最后會(huì)啥也沒(méi)做的。
也不要覺(jué)得要學(xué)習(xí)的有好多啊,不知道從哪學(xué)習(xí)起。我上面說(shuō)了,可以先學(xué)習(xí)最基本的,然后刷題,刷題是一個(gè)需要長(zhǎng)期堅(jiān)持的事情,一年,兩年。在刷題的過(guò)程中,可以穿插學(xué)習(xí)其他數(shù)據(jù)結(jié)構(gòu)。
-
算法
+關(guān)注
關(guān)注
23文章
4612瀏覽量
92900 -
數(shù)據(jù)結(jié)構(gòu)
+關(guān)注
關(guān)注
3文章
573瀏覽量
40132
原文標(biāo)題:我是如何學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算法的?
文章出處:【微信號(hào):TheAlgorithm,微信公眾號(hào):算法與數(shù)據(jù)結(jié)構(gòu)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論