ACM知識點 之 知識架構和要點分析
打算寫這個系列很久了,看到網上那些大牛一個個都寫了很多總結和知識點講解,逐漸明白自己的不足主要就是在基本功上。很多演算法和思路需要重新梳理才能更好的掌握和運用,正好集訓還有一個月時間,夠自己慢慢的把這些東西梳理完。
在我的認知中,演算法分為這幾大類:
- 搜尋
- 貪心演算法
- 資料結構
- 動態規劃
- 模擬
- 圖論
- 數論
- 幾何問題
1.搜尋
搜尋有很多種方法可供學習和使用,常用的有:
- 寬度優先搜尋(BFS)
- 深度優先搜尋(DFS)
- 啟發式搜尋
- 記憶化搜尋
這幾種搜尋方式各有千秋,其中DFS和BFS是很多演算法的基礎和核心,也就需要將其爛熟於胸。這裡先不過多介紹,會單開一篇文章講這些。
2.貪心演算法
貪心演算法也有三種公式性質的知識點:
- 區間選點問題
- 區間覆蓋問題
- 選擇不相交區間問題
可以說大多數的貪心問題都可以轉化為這三種問題中的一個進行求解。貪心演算法重在策略,這也是貪心和動態規劃不好掌握的原因之一,每道題都可能有變化,死記硬背之類的學習方式是萬萬不可取的。
3.資料結構
說起資料結構,那就真有的說了,作為幾乎與演算法齊名的一門學科,資料結構在演算法中的應用也可稱得上是大放異彩。
- 資料結構
- 優先佇列,雜湊表等基礎資料結構
- 並查集
- 區間資訊
- 樹狀陣列 (區間求和)
- RMQ問題(區間最小值)
- 線段樹 (動態範圍最小值)
- 點修改
- 區間修改
- 字串
- 字典樹
- KMP演算法
- AC自動機
- 字尾陣列
- 最長公共字首
- 紅黑樹等(也不是很懂,我還需要補充知識……)
資料結構的學習需要總結和不斷地優化,儘量寫成自己的模板,這樣無論是使用還是修改都不會出現無從下手的情況。
4.動態規劃
動態規劃(DP)作為重中之重,堪稱兩個極端的體現:最容易上手,最簡單的題目只要四五行程式碼,但是也最難精進,因為狀態轉移方程基本上沒有相同的,需要不斷的思考和總結之前的題目,這是一個循序漸進的過程。動態規劃也有一大票的現成理論和題目可以使用:動態規劃有很多很多的問題分類,其中很多是相通的,大概可以用這一張圖表示(來自 http://codevs.cn/):
- 揹包問題(重要的很,強烈推薦dd大牛的揹包九講)
- 最長公共子序列
- 最長單調子序列(遞增,遞減)
- 最優二叉搜尋樹(不是很懂,<演算法導論>上寫的)
- 整數劃分問題(劃分型DP)
- 石子歸併問題(區間型DP)
- 旅行家問題
動態規劃的學習需要花費很多時間,但是一旦入門,就是“柳暗花明又一村”。
5.模擬
模擬在日常的應用中也是很多的,在很多問題中都可以通過模擬來推匯出答案,比如基本的大數相加問題,採取模擬來一步步算出結果是最省力的,在時間差距不大的情況下,採取模擬的策略能使程式的複雜度有效地降低。
模擬問題沒有什麼理論模型,更多的是對現有條件的分析和總結。只要將現有的條件分析的七七八八,問題便迎刃而解。需要注意的是,很多模擬問題都會有大資料的限制,所以使用時間複雜度和空間複雜度儘量小的演算法是有效解決模擬問題的關鍵所在。
6.圖論
作為離散數學的重要組成部分,圖在演算法和實際生活中的應用可謂是桃李滿天下。幾乎與網狀有關的事物,都可以通過圖論進行建模和解決。圖論中經典的幾個模型包括:
在很多問題中,採用圖論的理論來解決問題,會比動態規劃更高效,也更容易理解。
- 最小生成樹
- 最短路問題
- 網路流
- 費用流
- 二分圖匹配
圖論的學習,離不開數學理論的支援。如果想好好鑽研圖論問題,那麼,良好的數學基礎是必不可少的前提。
7.數論
數論與圖論如出一轍,不再贅述(本人的數論功底不是很好,不敢妄加言論)。數論問題大概能分以下幾種(來自 http://codevs.cn/):
還是那句話,沒有良好的數學功底,圖論和數論的學習會比較吃力。希望大家能明白數學的重要性。
8.幾何問題
相比數論和圖論,幾何問題的解決方案要好得多。幾何方面有很多的定理可以使用,覆蓋的方面也比較廣泛。而且分類也比較少:
在我的印象中,幾何問題常常和貪心問題組合在一起,例如求解數萬個點中的最大多邊形面積等等諸如此類的問題。這要求演算法的基本功要紮實,能迅速判斷出篩選的條件和相應的演算法實現。
最後我想說的是,演算法的學習很費時間,也很費精力。很多時候,一個問題能困擾我們好幾天,百思不得其解。但是,這也是演算法的魅力所在。任何能輕易爬上的山峰都不會有美不勝收的景色。
演算法的學習更像是一場修行,保持一顆淡定且不斷前行的心才是最重要的。急功近利只會讓人止步不前,甚至不進反退。