算法漫游指北(第一篇):什么是數據結構與算法?為什么要學習數據結構與算法?怎么學習數據結構與算法?


一、什么是數據結構?什么是算法?

什么是數據結構?

Sartaj Sahni在他的《數據結構、算法與應用》一書中稱:“數據結構是數據對象,以及存在於該對象的實例合組成實例的數據元素之間的各種聯系。這些聯系可以通過定義相關的函數來給出。”他將數據對象(data object)定義為“一個數據對象是實例或值的集合”。

Clifford A.Shaffer在《數據結構與算法分析》一書中的定義是:“數據結構是 ADT(抽象數據類型Abstract Data Type) 的物理實現。”

大話數據結構:數據結構是相互之間存在一種或多種特定關系的數據元素的集合。

mooc-陳越:數據結構包括數據對象集以及它們在計算機中的組織方式,即它們的邏輯結構和物理存儲結構,同時還包括與數據對象集相關的操作集,以及實現這些操作的最高效的算法。

個人:就是把圖書館中的書轉化為一些字符數據存入電腦中,以及對這些數據對象集的操作。如找書,擺放放書等。

什么是算法?

還是圖書館的例子,如果一本一本找累死人,要是有個索引,先找哪一類這樣會快很多。如何查找其實就是算法。

算法是解決問題步驟的有限集合,通常用某一種計算機語言進行偽碼描述。通常用時間復雜度和空間復雜度來衡量算法的優劣。

算法的五大特征:輸入、輸出、有窮性、確定性、可行性。

輸入:零個或多個輸入。

輸出:一個或多個輸出。

有窮性:有限步驟后在可接受時間內完成。

確定性:每個步驟都有確定含義,無二義性。

可行性:每一步都是可行的。

算法設計要求:正確性、可讀性、健壯性、時間效率高和存儲低。

正確性:有輸入輸出,無二義性,有正確答案。

可讀性:方便閱讀。

健壯性:輸入不合法能處理

時間效率高和存儲低:時間空間復雜度越低越好。

這就是數據結構和算法。

數據結構有哪些?

 

數據結構可以簡單分為:排序、鏈表、列表、生成樹、樹、圖、棧、哈希

 

抽象數據類型可以分為:棧、隊列、集合、映射

數據結構中英文對照

Data Structure
​
Array                      數組
Stack / Queue              棧/隊列
PriorityQueue              優先隊列     
LinkedList                 鏈表
Tree / Binary Search Tree  樹/二叉搜索樹
HashTable                  哈希表
Disjoint Set               並查集 
Trie                       字典樹(單詞查找樹)
BloomFilter                布隆過濾器
LRU Cache                  LRU緩存
​

  

 

算法有哪些?

1、十大排序算法

  • 簡單排序:插入排序、選擇排序、冒泡排序(必學)

  • 分治排序:快速排序、歸並排序(必學,快速排序還要關注中軸的選取方式)

  • 分配排序:桶排序、基數排序

  • 樹狀排序:堆排序(必學)

  • 其他:計數排序(必學)、希爾排序

2、圖論算法

  • 圖的表示:鄰接矩陣和鄰接表

  • 遍歷算法:深度搜索和廣度搜索(必學)

  • 最短路徑算法:Floyd,Dijkstra(必學)

  • 最小生成樹算法:Prim,Kruskal(必學)

  • 實際常用算法:關鍵路徑、拓撲排序(原理與應用)

  • 二分圖匹配:配對、匈牙利算法(原理與應用)

  • 拓展:中心性算法、社區發現算法(原理與應用)

 

3、搜索與回溯算法

  • 貪心算法(必學)

  • 啟發式搜索算法:A*尋路算法(了解)

  • 地圖着色算法、N 皇后問題、最優加工順序

  • 旅行商問題

 

4、動態規划

  • 樹形DP:01背包問題

  • 線性DP:最長公共子序列、最長公共子串

  • 區間DP:矩陣最大值(和以及積)

  • 數位DP:數字游戲

  • 狀態壓縮DP:旅行商

 

5、字符匹配算法

  • 正則表達式

  • 模式匹配:KMP、Boyer-Moore

 

6、流相關算法

  • 最大流:最短增廣路、Dinic 算法

  • 最大流最小割:最大收益問題、方格取數問題

  • 最小費用最大流:最小費用路、消遣

 

部分算法中英文對照


Greedy                            貪心算法
Recursion/Backtrace               遞歸算法/回溯算法
Traversal                         遍歷算法
Breadth-first/Depth-first search  廣度優先搜索/深度優先搜索
Divide and Conquer                分而治之法簡稱分治法
Dynamic Programming               動態規划
Graph                             圖
Pre-order/In-order/Post-order traversal   前序/中序/后序遍歷
Binary Search                     二分查找
 

  

 

 

二、為什么要學習數據結構與算法?

此處省略一萬字...

 

三、怎么學數據結構與算法?

 

1、刻意練習:

指的是針對一個模塊的知識點,刻意的進行練習,並且要練習自己有缺陷跟弱點的地方,特別是讓自己有不舒服、不爽、枯燥的感覺。比如生活中的例子:乒乓球、台球、游戲等等。

 

2、反饋:

  • 反饋要即時,分如下兩種:

  • 主動型反饋:指的是找比自己做得更好的人,他們是如何做的。編程的話,就是閱讀大牛的源代碼:github, leetcode;還有第一視角的直播。

  • 被動型反饋:指的是高手給你的指點。比如:code review

 

核心概括一下:

  • 把學習算法和數據結構這個整體進行切分,可以看到是上面這么多種類,根據這些種類來進行學習。

  • 刻意的練習自己的薄弱環節。

  • 看大量的高手代碼,刷大量的leetcode題目。

  • 解題的時候要實現所有的方法,比較算法時間和空間復雜度。

 

3、算法面試面試時的切題四件套

  • Clarification(明確)

先把題目弄明白,看看有沒有什么比較陰險的地方,邊界啊范圍啊之類的

  • Possible solutions (可能的解決方案)

    • compare(time/space)(比較時間復雜度和空間復雜度)

    • optimal(加強)

    找到盡可能多的解,找到最佳解,多問,多思考

     

  • Coding (多寫)

    邊學邊練,適度刷題,用編輯器或者IDE在本地敲代碼

  • Test cases (測試案例)

看Solutions和Discussions板塊學習別人的代碼

 

知識需要沉淀,不要想試圖一下子掌握所有,不要一下子學習太多,然后還學的不咋地,最后放棄了。

 

總結一下就是:我們遇到什么困難,也不要怕,微笑着面對它,消除恐懼的最好辦法就是面對恐懼,堅持,才是勝利!加油,奧利給!

沒毛病,干就完了,奧利給!

 

 

 

 

 

然並卵,哈哈哈。

 

四、 如何通過LeetCode來進行算法題目練習

常見練習場景

場景1

拿到題目后就開始想着怎么寫代碼,結果寫了大半天,試着做了半天,不對,再繼續寫,還是不對,f**k,這么難,大sb,不做了

場景2

看完題目,這是要干啥,完全不知道怎么下手。

 

一些微小的算法學習經驗

其實,學算法,刷題蠻干是不行的,需要遵循科學的方法。

算法不是拼智商

算法不是純粹拼智商的,智商高,就一定很厲害,不夠聰明,就一定不行。算法是一種技能,是可以通過科學合理的方式訓練出來的能力。

智商的高低,當然會有影響,但這個先天因素無法改變,而科學合理的方法是大家都可以掌握的。

所以,首要的一點,是要意識到,算法不是只拼智商的,也是可以經由后天訓練習得的。

 

難度要循序漸進

有些同學喜歡上來就是干,上來就是終極難度的題目,覺得自己只要做出最難的,其它的就迎刃而解了。這種急於求成的思想要不得。

算法訓練是一個系統工程,需要循序漸進,太過於急功近利,反而容易因做不出難題而產生挫敗感,帶來反效果。

 

選擇題目不要看標簽

不要看標簽,不要看標簽,不要看標簽。標簽相當於問題的分類,看了標簽就會往那個方向去想,不利於自主思考。

 

練習時使用番茄時鍾

番茄時鍾是啥?百度一下

分配時間大概如下

 

第一階段:

分析階段:讀完題目,分析大概的要點,可能需要的知識點,此階段不動手,僅僅動腦。

在分析推導題目解法的時候,不要去想任何實現相關地事情,不用去想代碼怎么寫,不用去想要用什么庫,定義什么變量,用多少層循環,都不要想,就想着在邏輯上,這道題目要怎么解。

這樣做可以極大地降低你的心智負擔,使你高效地想出題目的解法。對於如何將想法變成代碼,可以留在下一個步驟,單獨來進行。

 

用時:1個番茄鍾,最多2個番茄鍾

重要的一點:如果最多2個番茄鍾過完,還是沒有任何思路,直接看解法,各種別人的解法,這不是抄答案!

然后背誦並默寫好的解法。直接應用五步刷題法。

第二階段:

驗證分析階段:

代碼寫起來,注意一些常見的小錯誤有:

  • 拼寫錯誤。變量命名要足夠清楚,不要用單個字母或者語意不明的單詞。

  • 數組邊界未考慮。

  • 空值未考慮。

 

用時:1個番茄鍾,最多2個番茄鍾。

注意:

如果中間發現了分析階段的錯誤或者疏漏。應該立即結束編碼,休息。

並且重新開啟分析階段的時鍾。

如果是重新開始分析再次進入代碼驗證分析階段,還是做的不對,用時超過3個番茄鍾,直接看討論或者答案。

 

切忌邊寫邊改方案。如果發現編碼過程狀態不夠好,應該加長休息時間,或者干脆結束掉。不要給自己留下低效的映像。

去開開心心的玩游戲,看電影吧,嗶哩嗶哩刷起來,別練習了。

 

 

第三階段:

進行解題分享階段:

 

分享時,建議大家就把自己番茄時鍾的執行記錄進行分享。最后標准的解法以及思路其實在 discussion 中都有。對他人有用的分享不是結果,而是:

  • 你在番茄時鍾中是如何規划的,也就是番茄時鍾的目標。

  • 你是如何分析,也就是思路。

  • 你的結論是什么,或者是你在執行時除了什么問題。

  • 你所總結出的題目的關鍵部分。也就是對問題域進行探索的經驗。

 

五步刷題法

刷題第一遍:

  • 5~10分鍾:讀題思考

  • 直接看解法,去國際站看最高票的回答

  • 背誦、默寫好的解法

  • 多解法,比較解法優劣

刷題第二遍:

  • 馬上自己打開瀏覽器寫->leetcode提交

  • 多種解法比較、體會->優化

刷題第三遍:

  • 一天后,再重復刷題

  • 不同解法的熟練程度->專項練習 刷題第四遍:

  • 一周后:反復回來練習相同題 刷題第五遍:

  • 面試前一周恢復性訓練

     

認真學習,堅持訓練。

 

最大的誤區

做算法題只做一遍!!!

 

 

關鍵的關鍵

  • 現在就動手

  • 注冊LeetCode

  • 練習-堅持-機會給予有准備的人

 

參考資料

[1]https://blog.csdn.net/u013164931/article/details/80189351

[2]https://www.cnblogs.com/kubidemanong/p/11847944.html

[3]https://blog.csdn.net/weixin_41278720/article/details/90268965


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM