程式設計師練習演算法的幾個實用技巧

2022-01-20 08:14:07 字數 3756 閱讀 6295

上週在公司內部分享了自己練習演算法的心得和經驗,有小夥伴表示分享的內容給他帶來了價值,也很具備參考意義,於是就演算法寫成文章分享出來,近幾個月來,自己每週都會花1、2小時在 leetcode 上面練習演算法,短短幾個月下來也陸陸續續交出 40~50 的解題作業,算是乙個小小的里程碑吧,以下是我最近的刷題記錄:

所有的解題記錄我傳到了的公開的 github 專案,有興趣的可以訪問鏈結看看

偶爾在演算法群裡也有小夥伴總是在問:「刷題太難了,自己總是虎頭蛇尾,你們是怎麼堅持下來的 ?,有什麼方法嗎?」,其實很多人剛開始都是熱情滿滿,然後馬上就三分鐘熱度了,這其實也很正常,我也通過自己幾個月的探索和堅持,踩了不少坑,所以總結了不少我個人覺得行之有效的刷題經驗,跟大家分享一下,也避免大家後續再走彎路

總體大綱如下:(預計 5分鐘能讀完)

為什麼要練習演算法 ?

如何有效的練習演算法 ?

最後總結(關鍵的關鍵)

相信高手都明白演算法和資料結構是基本功,但是還有很多剛入行的新人不是很明白,我的個人觀點如下:

常用的程式語言大多都是對資料結構的封裝,所以很多面試官特別喜歡問以下的問題,例如:

而且根據我了解的很多面試官其實根本不在乎你使用什麼程式語言,熟練使用什麼技術框架,這些只是「術」的層面,他們更加在乎你是否具備解決問題和抽象問題的能力,這些才更加具備長期的價值,更加接近「道」的層面,那麼如何考察呢 ?就是通過演算法,最好是通過在白板上給出解題的過程和思路,例如 google 就特別喜歡這樣做。閒話扯的有點遠,我們下面進入正題

一:端正心態和學習態度

我覺得既然下定決定要去學習,那麼首先要調整的就是心態,這個社會大部分人都很浮躁,想要速成,但是學習是不可能速成的,需要先定好目標,然後一步一步向前行,首先我先推薦一本書《異類》

這本書通過各種案例向大家傳遞了關於「一萬小時「的理論,而且不是勤勤懇懇的重複的一萬小時,必須是有目標,有階段,不斷按曲線成長的」一萬小時「,不然的話你也只是在感動自己而已,任何不經思考的學習和練習都是徒勞

如果要按照這個理論,就是說乙個普通人,每天要花 3-4 小時的學習成長,差不多持續十年,你才有可能成為行業的高手和專家,所以要明白很多成功都不是偶然的,很多看似輕鬆達成某些成就的人,背後都付出常人無法理解的痛苦和努力,就像那些看上去身材很好的人,他們顯得很年輕,穿衣服也很好看,但是你沒有看到他們咬緊牙關在鍛鍊的時間,bob 大叔在《程式設計師的職業素養》一書中也說過一句話」任何專業人士都需要保持刻意連續,鋼琴家,醫生,律師,拳擊手,吉他手,樂隊等等,想要成為專業人士都必須保持刻意的練習「,所以大家應該明白學習沒有捷徑,想要成為專業人士,就要付出相應的努力

二:用玩遊戲的心態來學習

學習和看書那麼苦,那麼累,還要堅持那麼久,我們能不能想一些方法來減輕這種痛苦的感受?

答案是有的,也是我自己認為行之有效的一種,那麼就是:用玩遊戲的心態來學習(關於遊戲如何利用反饋機制讓人上癮的細節我就不詳細說明了,不了解的同學有興趣自行去 google 了解反饋機制對大腦的刺激)

那麼具體如何操作呢 ?我簡單總結以下兩點:

回想一下你是如何成為 英雄聯盟/王者榮耀 高手的 ?

主要分以下幾步:

主動嘗試:進入遊戲隨便選擇乙個英雄,簡單看看技能嘗試玩一玩

熟悉常用技巧:慢慢熟悉使用英雄所需要裝備,順便熟悉地圖,例如躲草叢

開始學習如何見招拆招:開始了解敵方英雄的技能和套路,並且熟悉對線的技巧

主動學習和練習:對於自己還未熟悉的英雄和技能反覆練習,慢慢形成長期記憶

以上是玩遊戲的步驟,那麼對於練習演算法,我們也可以用同樣的步驟:

熟悉常用技巧:慢慢熟悉常見的資料結構,例如:陣列/鍊錶/queue/set/hash/tree 等等

開始學習如何見招拆招:熟悉常用演算法題的套路和技巧,例如:雙指標/雜湊/位運算/反轉鍊錶/二分/遞迴等等

主動學習和練習:對於自己還未熟悉的型別結構反覆練習,慢慢形成長期記憶

以上可以發現其實玩遊戲的思路可以用在演算法練習上,而且效果還不錯,不過僅僅做到以上幾點,還不能成為乙個遊戲高手,通常如果你想在遊戲裡面成為高手還需要做到如下幾點,,我稱之為:

feedback 持續反饋:

多打排位賽和天梯,跟自己等級相同的人對抗(對應到練習演算法就是找符合自己難度的題目,多練習)

多逛論壇和高手討論,多看前人的攻略並且自己不斷的總結心得(相同)

多看相關的比賽和直播,看高手之間競技,並且學習套路(相同)

如果能用以上的方法,再加上持之以恆的心態,應該就能成為乙個(遊戲/演算法)的高手了

三:刷題的注意事項

上面總結了如何調整心態,下面我們講講在刷題階段的幾點注意事項

對於初學者練習演算法,我有以下幾點建議,簡稱 cpct 法:

認真審題 clarification:一定要明確作者出題的意圖,複雜度的要求等等,例如作者想考察你的二分查詢,你非要用暴力破解,雖然也能解題,你失去這道題最精髓的內容

反覆練習 coding:多寫**,多練習,演算法就是三分學,七分練

覆蓋測試 tests cases :當提交的 case 被判定不通過的時候,是一件很痛苦的事情,所以提交 case 前盡量在本地最好足夠的測試,這點也可以用在我們平時寫**的習慣上

四:介紹一下複雜度

有乙個很經典的演算法問題,就是要計算 1+2+3+4....+100 的總和的方法:

因為 100 也不算很大,很多同學估計這樣計算:

勉強計算 100 次後,我們得到 5050 的最終結果,

我們再把問題擴大一下,如果要計算的值不是 100, 而是 1 + 2 + 3 + 4 .... 一直到 1000, 或者 10000 呢 ?如果值是 1000,那麼就要重複計算 1000 次,如果值是 10000 ,那麼就要重複計算 10000 次,負責計算的人估計會崩潰了(沒錯,計算機也是這麼想的),隨著 n 越大,要計算的次數越多,這種需要計算 n 次的演算法,我們評估它的時間複雜度為:o(n)

這時候還在讀小學,並且不願意透露姓名的高斯同學,發現的計算的規律,並且總結的求和公式:y = n * (n + 1) / 2

使用這個公式不管要計算的值有多大,得到的結果都是相同,而且永遠只需要計算一次,這種方法我們評估它的時間複雜度為:o(1)

這也是演算法的目的:在保證結果正確的同時,將時間複雜度和空間複雜度降到最低

常見的大o表示法和常見的術語:

從優 >> 差的複雜度排序:

o(1):常數複雜度

o(log n):對數複雜度

o(n):線性複雜度

o(n log n):nlogn 階

o(n^2):平方

o(n^3):立方

o(2^n):指數

o(n!):階乘

關鍵的關鍵

多練習,刻意練習(找到自己缺陷,反覆練習)

推薦** leetcode (按照型別分組,按照型別練習)

feedback 持續反饋(主動學習)

重在實踐:三分學,七分練(切莫貪多,貴在堅持)

GIT的幾個實用技巧

一 修改本地倉庫的遠端倉庫url 從別的專案不想fork過來,而想自己新建乙個倉庫重新上傳,並保留完整日誌,可使用下方法 git remote set url origin二 刪除遠端分支 github上有乙個遠端測試分支,已經好久不用了,現在想刪除掉。git push 遠端名 分支名 git pu...

Linux中的幾個實用技巧

一 vim 儲存乙個沒有許可權的已編輯檔案 剛安裝好ubuntu,用vim對vim etc ssh sshd config檔案做了更改,儲存時才發現對該檔案僅有唯讀許可權,不能進行儲存操作。告警內容如下 解決方法1 把檔案關閉,獲取許可權以後再重新開啟。但是如果你已經做了大量更改,這樣做會很浪費時間...

delphi 程序處理的幾個實用技巧

1.程序的掛起與恢復 程序掛起與恢復 function suspendprocess hprocess thandle dword stdcall external ntdll.dll name zwsuspendprocess function resumeprocess hprocess tha...