1. 程式人生 > >(筆記)如何快速攻破傳統演算法和資料結構

(筆記)如何快速攻破傳統演算法和資料結構

知乎上的SimonS大神的講座,給想學習演算法的童鞋的一些建議:

https://www.zhihu.com/lives/795264798257479680

一,QA部分:

1. 985 大二 專業軟工 沒有oi經歷。如何一年時間拿到ACM區預賽銀牌?
主要參考後續的live,實際是有可能的。只需要選擇對的方法


2. 如何高效刷演算法題(演算法面試題)呢?堅持不看答案要卡很久,效率低。
可是看過答案又記不住,下次遇到接著卡殼,如此反覆好受打擊
主要做到訓練以後能舉一反三。

3. 接著作者舉了一道面試的演算法題(字串chain)?
後續研究看看(屬於LeetCode中等難度)



答案是一個DP的解
live主貼出了一道python的解法


4. 老師你好,我現在大二軟體專業,對演算法的學習有點力不從心
靜不下心來,感覺這也很難那也很難,那種焦躁的心情怎麼解決?
是不是演算法不適合我?
live主認為提問者現在處於浮躁的狀態,很難靜下心。
leetcode比競賽簡單,屬於程式設計入門(不算競賽入門)
leetcode中等偏上屬於演算法入門。

5. 資料結構怎麼學,是否按照書本來打程式碼?
不推薦書本打程式碼。
需要一個能檢驗你程式碼正確性的平臺。一個oj,leetcode等。

6. 普通二本生有必要入acm坑?
無論學校背景,甚至職校學生都推薦參加ACM。

7. 大二ACMer,用一年時間來訓練,如何訓練好?一些基本的演算法都有了解。
還有大一新生,應該怎樣給他們安排訓練計劃?沒有演算法基礎
先組三人隊伍,多參加線上比賽。
大一新生,多做內部個人比賽。

7. 大二ACMer,用一年時間來訓練,如何訓練好?一些基本的演算法都有了解。
還有大一新生,應該怎樣給他們安排訓練計劃?沒有演算法基礎
先組三人隊伍,多參加線上比賽。
大一新生,多做內部個人比賽。


8. 如何比較好等準備機器學習演算法等基礎模型?
多掌握統計學等基礎 特徵工程


9, 學習演算法,是不是數學知識要求很高呢? 需要哪方面等知識鋪墊?
傳統演算法對數學知識要求並不算太高。(線性代數,初等數論競賽用)
但是演算法分析方面對數學要求會高一個層次。
(線性代數,離散數學,初等數論,組合數學等等)
機器學習要求數學更高(線性代數和統計學,微積分)


10. 影象識別演算法怎麼入門比較好,工程應用?
模式識別


11. 怎麼學資料結構才是比較好的方法,老師都是讓我們照著課本打程式碼,
這樣感覺跟背公式應付考試一樣。
首先需要對知識體系有一個系統的瞭解,接著再針對性的做題目。


12. 寫某些高階資料結構容易寫炸,要花半天功夫去除錯,怎麼辦呢?
設計測試,寫一塊測一塊。
增加一個模組,就測試一塊保證起正常。


13. 本科生參加競賽和刷leetcode,如果遇到自己想很久都想不出來的問題是否應該
直接看答案?
Leetcode 有不少提示,如果提示看不懂參考Discuss(不看Show程式碼)


14. 機器學習方法,學習資料結構通過國內網際網路公司筆試,程式語言
選擇python還是c++?
live主兩者都要學python和c++, 甚至還需要學java
難點在於機器學習的核心思想,統計學等


15. ACM選手如何系統學習複雜的演算法和資料結構?
複雜每個人定義不一樣。
例如:樹形動態規劃,解決哪一類問題?去哪裡解決這一類問題(做題)
反思總結


16. 請問計算廣告的後端工程師需要掌握像演算法工程師一樣的機器學習
的相關演算法來提高核心競爭力嗎?
live主認為沒必要。
後端工程師的未來是-》系統架構師,優化,併發量。
機器學習演算法-》全棧工程師-》搶飯碗?


17. 演算法導論這本書如何高效使用呢?
不建議入門使用。在自認為掌握紮實了再去學習。


18. 如何刷Leetcode和機器學習演算法?
1)按題目序號
2)按題目從簡單到難
3)按隨機
因人而異
對機器學習的基礎,特徵工程。


19.在完全沒有演算法基礎,僅有一點c語言基礎上,
有沒有學習演算法列表(由淺入深這種),
如何才能掌握一個演算法呢?
leetcode由easy - medium - hard
一個演算法大綱:
https://www.zhihu.com/question/23148377/answer/36824071


20.普通應用開發工程師,比如前端開發,移動開發,需要對資料結構和演算法
學習多少?需要花時間學習麼。如何平衡學應用的時間和學演算法的時間?
前端不是有必要去學習演算法。
如果感興趣每天做1~2題Leetcode就足夠。


21.底層演算法C++工程師,偏影象處理方向,如何入門相關演算法?
模式識別相關。


22.Coursera還是直接看書好?
最高效的學習方法是做題。
瞭解框架概念,做題。




23.資料結構公開課,練習題?
MIT的官方課程:
Introduction to Algorithm
Advance data structure
練習就刷leetcode,poj可以了。




24.機器學習該如何入門?
普通程式設計師如何像人工智慧靠攏
https://www.zhihu.com/question/51039416/answer/134564100




25.為什麼面試中DP(動態規劃)比較多?
除了DP其他都可以套模版來解決。




26.如何尋找演算法的資料?比如0基礎,貪心,
分治,回溯這些?比如我在做一道題以後,我想對
這個演算法瞭解更多的情況。
專題訓練,後期看權威著作。如算導




27.在oj上刷題,遇到不會的要如何處理?應該花多少時間
去看題解,看了題解以後怎麼辦?如何防治下一次遇到同樣的
還不會呢?
看完答案,手動實現一遍。對同類題做專項訓練


29.徒手寫演算法程式碼的能力重要麼?有什麼用?
白板程式設計。看出對程式語言的熟練程度,
第一時間想到埋下的坑。邊界條件。


30.cpp和java寫演算法容易忘記,python不容易忘記。
因為python更像自然語言。c++要考慮更多問題。


31.一個學習大綱
live主推薦的一個給演算法,系統工程師等的學習大綱:
https://zhuanlan.zhihu.com/p/22543073

二,正文大綱



如何快速攻破傳統演算法和資料結構
演算法工程師內功篇(一)


*為什麼面試官都喜歡考察程式設計師基礎演算法?
*如何高效,系統性地學習演算法和資料結構?
*為什麼大家普遍覺得動態規劃較難理解?
*學演算法是否有必要參加OI/ACM等演算法程式設計?
*如何平衡自己在演算法競賽和其他方面的精力?
*學習傳統演算法對日後工作的幫助具體有多大?
*學習傳統演算法對機器學習的幫助具體有多大?
*面經分享

1)為什麼面試官都喜歡考察程式設計師基礎演算法?

*面試者工齡在3年以內尤甚


*考察底子是否紮實,即使該知識點可能用不上
例如快取管理LRU演算法。造輪子
計算廣告中,查詢手機IMEI集合(資料大)


*考察是否聰明,能否在短時間提供解決方案
例如動態規劃(前面的字串相識的問題,計算編輯舉例,自動機)


*避免產生時間複雜度上的常識性災難
例如濫用MAP容器。

2)如何高效,系統性地學習演算法和資料結構?

*先系統後高效
*何為系統性學習?
    * 全面(均有涉獵但不必深究)
    例如Map容器,紅黑樹,實現方式,特性等等。一種對平衡樹無法解決問題的拓展
    * 應用(自己手動編寫)
    例如對平衡樹的特性有過了解,自己手動實現過平衡樹的幾種實現和變種。
    * 思考(加深理解,舉一反三)
    知道平衡樹的多種實現,思考對比多種實現的優缺點和關係,如何進一步優化呢?
    能更深入理解你對知識點的理解

作者認為如果是一個985/211等學生半年時間從0開始補演算法是可以達到一個省賽金牌的水平

* 如何高效做到系統性學習?
    * 全面(找一份學習大綱,可以參考live主在知乎上的回答)
    作為一個技能樹的標準
    https://www.zhihu.com/question2/3148377/answer/36824017
    * 應用(找題庫,LeetCode/POJ/ZOJ等,還有USACO, URAL)
    * 思考(取若干道同類型的boss題,獨立完成)
    舉例:學習了dynamic Programming 。然後去leetcode上把dynamic programming標籤
    等題目都做了。
    * 再思考(閱讀《演算法導論》等著作)也叫深入思考
    live主認為,應系統學習過一遍常規經典演算法以後再去看演算法導論,
    系統性深入瞭解補充自己欠缺的地方。

* 針對競賽
    * 動手實踐遠比看書重要
    live主認為多寫程式碼比多看書更重要。(針對競賽)


    * 不要在自己覺得過難的知識點上死磕
    例如覺得DP已經有一定深度了,但是不應該在DP上鑽牛角尖,因為還有大量資料結構需要學習


    * 要用自己擅長的方向(DP,數論,圖論,計算幾何,資料結構)
    因為ACM是3人組合,每個人需要有自己的擅長方向。類比Dota遊戲,每個英雄要有自己的發展方向。
    法系英雄不要補物理裝,而物理英雄不要出法系裝備一樣!
    live當年參加ACM的時候,主攻DP和初等數論, 隊友攻計算幾何和資料結構,另外一個隊友思考Trickle
    在有限的訓練時間內,讓整個團隊的實力得到一個最大化的提升。


    * 每次解題都要計時和統計提交次數
    給自己一個壓迫感,給自己比賽有一個氛圍。
    裝平時訓練中要有掐時間的習慣。才能在比賽中做到有條不紊。

3)為什麼大家普遍覺得動態規劃較難理解?

參考


(不知道為啥,我覺得這個是統計學中計算數學期望的題目呢?)
如果偷兩件銀行1,2風險是:
風險計算  1 - (1 - R1)* (1 - R2)


動態規劃和記憶化搜尋的區別?
DP應用了記憶畫搜尋的思路。




暴力列舉:N家銀行選或不選,O(2^N)的時間複雜度,不可取
思考子狀態:
    * 列舉計算只搶前i家銀行的最大金額?不能,有後效性,要增加緯度
    * 列舉每個概率下的最大搶劫金額?太麻煩,可能有精度災難
    * 列舉每個搶的金額下最大逃脫概率?可行,輕鬆解決
狀態:F[i], 表示搶i塊錢的最大逃脫概率
初始化:F[0] = 1, 其餘為 -1(搶0塊錢肯定100%逃脫)
轉移方程:F[i] = max{f[i], f[i-Mj]*(1-Rj)}
時間複雜度:金額最大是10000, 所以是O(kN)


*目標:求解決策過程最優化的數學方法
*步驟:
    * 尋找子問題(最優子結構)
    * 確定狀態(時空複雜度)
    * 確保沒有後效性
    * 尋找轉移關係及合適的列舉方向
    * Coding!

4)學演算法是否有必要參加OI/ACM等演算法程式設計競賽?

OI:無論從功利目的還是興趣出發,除非你有很好的環境和很大的自信
並且有豐富的閒餘時間,否則均不建議參加
    * 初高中學業壓力大,OI不能作為主要學業
    * NOIP已經沒有了保送一流名校的資格
    * 為未來選擇一個好的競賽氛圍和好隊友更重要


ACM:無論你在演算法方面是否有所建樹,都建議參加
    * 感受比OI更激烈的競賽氛圍
    * 增加團隊高效溝通合作的技能點
    * 未來就業的金牌敲門磚

5)如何平衡自己在演算法競賽上和其他方面的精力投入?
參考圖


6)學習傳統演算法對日後工作的幫助具體有多大?

* 基礎紮實,Coding速度和質量都有極高的保證
    * 中介軟體開發,可快速勝任造輪子的崗位
    * 極大降低加班時間,提升程式設計師生活幸福感


* 解決問題能力強,擁有較高的計算機思維
    * 擅長用樹,圖等非線性資料結構將問題抽象化
    * 擅長計算時間空間複雜度,保證公司資源的最大化利用
--
* 場景:2016年淘寶雙11有10.5億筆交易,假設擁有這些交易的日誌檔案,
如何快速統計出當天銷量最高的100件商品?


* 簡化問題,在不考慮記憶體瓶頸大情況下,用Hash統計每件商品的成交量,
並同時利用最小堆維護當前銷量最高大100件商品。遍歷完所有日誌後,堆中儲存
著的即是答案。演算法達O(kN)時間線性複雜度。

7)學習傳統演算法對學習機器學習的幫助具體有多大?

* 許多效能優化方向(線性代數相關尤甚)
* 可以在多項式時間內尋找最優解
圖論在計算廣告中的應用
https://zhuanlan.zhihu.com/p/23562855

8)面經分享

* 在一列無序數列中尋找中位數
暴力:排序取中間點nlogn
快排分治思想:partition之後丟掉一部分。 線性複雜度
* 給出10萬條人和人之間的朋友關係,求出這些人中有多少個朋友圈
無向圖,求多少孤立島。連通分量
暴力:DFS,BFS搜尋。
並查集
* 在一個很長的二進位制串中,求除以3的餘數
正規做法:自動機。遞推關係
* 在一個需要頻繁更新的業務場景下,求出區間和
線段樹,區間樹(簽到題)
* 在一個原本應該成對出現的數列中,尋找唯一一個不成對的數
比如2個2,2個4.
位運算異或

最後我發現《資料結構與演算法分析C/C++語言描述》這本書算是比較全面性介紹了演算法根據大綱來(也叫小演算法導論 因為這本書涵蓋的範圍最廣泛),

雖然《演算法4》推薦的人熱度更高,但是《演算法4》介紹的演算法並不算全面,可以作為補充材料閱讀。

清華大學的那套《資料結構C++》也屬於這種情況,雖然每個章節都有一定深度的展開,資料也足夠詳細但是像動態規劃這樣的都沒有介紹到。

暫定以《資料結構與演算法分析C++語言描述》為主要學習課本,演算法4(有介紹字串距離,正則表示式)的部分可以進行閱讀

《資料結構C++》裡甚至有哈夫曼樹和紅黑樹的實現,深度也足夠。可以進行擴充套件性閱讀。

最後再考慮閱讀《演算法導論》