算法訓練:噓,別人我不告訴他


算法 or 遊戲

編程、數學是十分適合自學的,因爲一道題對不對,您可以立馬得到答案。

哪怕您很喜歡編程,也會如我一樣在這條路上遇到無數問題:

  • 對一個題目,苦思冥想好幾天;
  • 看到大佬的博客、代碼,不僅思路清晰,功能實現出來了,代碼還很簡潔、高效,突然有點沮喪、失意;

這些問題,我們都會遇到,但我們也會一直學習,也許我們都不是很有毅力。

  • 一個題目一直想,喫飯想、走路想、有時做夢也會夢到,最後解決了您可以想一想那感覺多爽;

  • 其實您看懂了一篇博客或一段代碼,不就向大佬邁進了一步麼,有好的教程在這裏,您應該特別興奮纔對呀。失意了就想一想自己成功時的體驗,您能找到那種感覺的;

  • 如果下定決心想超越大佬,不完全是比大佬更努力,因爲這只是低層面的競爭,而是首先在見識和格局上要比大佬高,氣度要更大。學習不是努力讀更多的書,盲目追求閱讀的速度和數量,這會讓人產生低層次的勤奮和成長的感覺,這只是在使蠻力。要思辨,要踐行,要總結和歸納,否則,只是在機械地重複某件事,而不會有質的成長的。

我們再不斷的演化,我相信人也是可以不斷成長的,所以專注於不斷訓練和發展自己。

而編程是工科,在於實現的細節。真正的功夫都在自己的練習之中,信心和水平只能在每一次成功解題和程序成功運行中提高。

那這種訓練模式,是快樂,還是痛苦呢?

真是先苦後甜,一場激情不斷的遊戲。

TA是一款解謎、策略類遊戲,您需要先熟悉TA的各種設定、各種道具、各種技能,最後去解決一個問題。

  • 各種道具:所有結構的地基(數組、鏈表、改進的結構),一對一結構(棧、隊列、哈希、串、廣義表),一對多結構(樹、堆)、多對多結構(圖)、集合、排序與查找…

  • 各種設定:算法設計、算法分析、算法思想(遞歸、遞推、枚舉、二分、倍增、模擬、貪心、分治、回溯、剪枝、緩存、搜索、構造、近似、仿生、隨機化、雙指針、時空互換、動態規劃、啓發)…

  • 各種技能:數論、圖論、找規律、計算幾何、搜索、概率分析、並查集、線性規劃、矩陣、AI算法…

這些工具一定要內化,因爲光是知道是沒用的,要感受到、觸摸到。

每個工具都能帶給您不一樣的體驗,如果您可以掌握,比較適合走算法路線,多參加算法競賽,不過軟件方面就會菜一些。

數組、鏈表、哈希表、二叉樹、排序算法等一些基礎知識,對大多數人來說是沒什麼問題的。但是一旦進入到路徑規劃、揹包問題、字符串匹配、動態規劃、遞歸遍歷等一些比較複雜的問題上,就會讓很多人跟不上了,不但跟不上,而且還會非常痛苦 — 那比較適合走軟件方面,多參加軟件競賽,不過算法和數學方面會菜一些。

 


基礎的設計能力:不知道如何下手怎麼辦?

我們實現程序裏的算法時,其實就是寫一個或者若干個函數。

有時候,我也不知道該如何下手。

沒關係,我們可以先分析一下問題的參數:

  • 應該傳什麼參數給函數(作爲輸入參數)
  • 函數處理完後,應該把什麼數據作爲結果返回(作爲輸出參數)

函數參數搞定後,再推導返回類型、函數名,於是函數原型就出來了:

返回類型 函數名(函數參數)

對一道問題完全沒想法時,多半是沒有分析好,這時候不要急,一步步分析。

分析好函數原型以後,再確認條件:

  • 不變式
  • 終止條件
  • 邊界條件:避免不合理的輸入參數來攻擊程序。

如果程序功能和某一數據結構的數據關係相同,就可以用數據結構來實現。

P.S. 數據結構:數據結構:把數據放入結構裏,通過結構裏最基本的計算方法(增、刪、改、查)操作數據。

 


基礎的建模能力:數組、鏈表,以及改進的結構

好的結構設計可以簡化算法複雜度,算法通常是和數據結構一起學習的。

所有數據結構在存儲上,都只有倆種形式:

  • 數組:順序存儲
  • 鏈表:鏈式存儲

所有的數據結構建模,基本都是建立在這倆種存儲之上的,掌握好數組、鏈表,數據結構的建模基本沒啥編程上的問題了。

大概,有一個性能上的問題:

  • 數組便於直接訪問,方便數據的 查找 Θ(1)\Theta(1),而 插入、刪除 麻煩 Θ(n)\Theta(n)
  • 鏈表強調前後關係,方便數據的 插入、刪除 Θ(1)\Theta(1),而 查找 麻煩 Θ(n)\Theta(n)

所以,就有了許多新的數據結構來改進:
 

  • 跳錶(skip listskip~list):通過隨機化,形成了一種可以二分查找的有序鏈表。

    查找、插入、刪除都是:Θ(log n)\Theta(log~n)

    大概長這樣:


 

  • 哈希表:通過隨機化,把一個比較大的、稀疏的空間,映射到一個比較小的、緊密的空間中。

    查找、插入、刪除都是: Θ(1)\Theta(1),但佔用空間大,利用率低。

    數組、哈希表對比:數組在處理多個維度時變得很複雜,而哈希表可以將多個維度的數據映射到一個維度。

    大概長這樣:

 

  • 數組鏈表:本質是一個鏈表,這是語言學上的偏正關係,如牛和奶、蜜和蜂,主要是看最後一個詞是什麼。

    因爲數組鏈表,主要是便於在沒有指針、引用類型的高級程序設計語言中使用鏈表結構,只是單純的模擬鏈表,所以複雜度和鏈表一樣。

    插入、刪除: Θ(1)\Theta(1),插入、刪除只需要修改遊標,不需要移動元素。

    查找: Θ(n)\Theta(n),使用動態數組可解決表長難以確定的問題。

    大概長這樣:


 

  • 鏈表數組:本質是一個數組,類似圖的鄰接表、樹的孩子鏈,是一種順序分配和鏈式分配相結合的存儲結構。

    查找:Θ(log n)\Theta(log~n)

    插入、刪除: Θ(1)\Theta(1)

    大概長這樣:

很多源碼都有鏈表數組,如 :

  • HashMap 裏的 table
  • Linux 內核 Buffer 裏的 hash_table
  • Linux 內核進程調度裏的 timer_list
  • Linux 內核網絡模塊裏的 sock_array
  • Linux 內核網絡模塊裏的 ip_protols
  • LinkedHashMap 裏的 table

對比一下:

數據結構 查找 插入 刪除
數組 Θ(1)\Theta(1) Θ(n)\Theta(n) Θ(n)\Theta(n)
鏈表 Θ(n)\Theta(n) Θ(1)\Theta(1) Θ(1)\Theta(1)
跳錶 Θ(log n)\Theta(log~n) Θ(log n)\Theta(log~n) Θ(log n)\Theta(log~n)
哈希表 Θ(1)\Theta(1) Θ(1)\Theta(1) Θ(1)\Theta(1)
數組鏈表 Θ(n)\Theta(n) Θ(1)\Theta(1) Θ(1)\Theta(1)
鏈表數組 Θ(log n)\Theta(log~n) Θ(1)\Theta(1) Θ(1)\Theta(1)

後面的高級數據結構,就是基礎的底層結構通過搭積木式的組合得到。

 


解題技巧:也說不清楚,就是對這道題有 feel 呀!

認知心理學說,人類最有效地解決問題方式,是"目標-手段分析法"。

  • 先確認目標
  • 再一層一層地分解,大問題變一組小問題
  • 每一個小問題都有實現的手段,而後去做就完成啦

流程大致是:

  • 確認目標
  • 分析過程
  • 分而治之
  • 行行實現代碼
  • 代碼封裝

最重要的是確認目標,最難的是分析過程,因爲這是腦力活;後面的代碼一行行實現在封裝,只是體力活。

分析多了,就會有一些感覺、套路。

比如,一般是從暴力開始思考,而後再進一步思考怎麼去優化複雜度:

  • 常見的枚舉可以看一看枚舉的範圍是否有序,可以考慮用二分;

  • 雙重循環看一看是否可以用雙指針(快慢指針、對撞指針);

  • 一些要查找的O(n)複雜度的部分是否可以用 map()set()map(鍵對應值,可以統計頻率)、set(只有值,存在或者不存在);

  • 括號、迴文之類可以思考一下能否用棧;

  • 一些暴力搜索的部分看一看是否存在根本不可能到達的狀態可以考慮剪枝;

  • 暴力搜索時看看是否有可重複利用的狀態用 mapmap 或數組把狀態存起來(記憶化搜索),然後再看看是否可以用動態規劃;

  • 一些枚舉的範圍很大一看就知道不可能 acac,那思考一下是否可以直接推出結論或數學公式(貪心的思考方向);

  • 一些感覺是動態規劃的題目,貌似每一個狀態都是有規律的可以嘗試用打表這種比較賴皮的方法;

  • 一些需要反覆計算的部分如果是固定的,可以考慮先計算好然後把它存起來,下次直接拿來用(前綴和思想);

  • 一些題目的條件和經典題型很像的可以考慮直接套用經典題型(例如 0101揹包模型,完全揹包模型);

  • 一些常見的操作可以看看有沒有現成的類或方法可以直接拿來用(例如 javajava大數、排序、字符串反轉、拼接等常見操作);

  • 一些數字的操作可以看看是否涉及到二進制,可以嘗試下異或、&這些操作(位運算的騷操作);

  • 動態規劃的題目看一看這一次的狀態和上一步的狀態是否離得很近,如果離得很近可以考慮狀態壓縮,降低空間複雜度(例如斐波那契,每一次的狀態只和前面兩步狀態有關);

  • 如果題目給出了樣例範圍可以先通過樣例範圍反推出算法的時間複雜度,從而考慮題目大概可以用什麼算法。

一般能有這種感覺,就是把知識【內化】爲感覺了。

那具體怎麼【內化】呢?

這個就得在《攻略》裏說了。

 


攻略:新手、老手和大神之間的差異。

前置:數據結構是什麼,以及作用?

如果不知道數據結構,請猛擊:《數據結構 | 從哪裏開始?

既然數據結構這麼重要,該怎麼訓練呢?

  • 先系統性學習所有數據結構(數據如何建模+實現增刪改查),做相關的題,做滿三道就學下一個。

  • 做相關的題:按類別 -> 畫圖分析增刪改查的動態過程 -> 手寫代碼 -> 手敲 -> 對比題解 -> 揹着敲。

  • 廣泛涉獵,一本一本書地學,一個一個知識點的認真總結,從長遠來看,纔是真正“高效率”的學習方法。

如果想未來是一個深不可測的計算機專家,在 2121秒 或 2424小時 內改變自己的人生,或者提高自己實際的編程水平,這是不可能的。

您得試試連續 2424個月 不間斷的努力提高自己。

曾經有人拿奧數題問數學家 丘成桐,而丘成桐表示自己不會做,也不值得做。

因爲奧數注重於巧妙的技巧,而數學家卻不是這技巧的集合。

就像真實世界裏,警察是最擅長破案的,警察不是靠像福爾摩斯式的超高水平的推理,而是挨家挨戶的排查,靠平時聯絡的線人、以及平時對這片區域的情況,還有網絡攝像頭。

真實的環境中,“孫子兵法”、“博弈論” 都沒啥大用,智慧主要體現於 明智的選擇、開闊的眼界、春去秋來的勤奮。

對於一位數學家也是如此,相對於解題技巧,數學家更需要的其實是 勤奮、眼光和思想。


系統訓練之後,要以實踐爲主(遇到不會的再學):

OJ訓練:題目如何安排

學習的目的不能是爲了“解除焦慮”,而是爲了解決您真正遇到的問題。

很多人莫名其妙地焦慮,然後學了一些熱門的新知,一瞬間獲得那種 “哇,我懂了,我瞭解了新技術”的廉價快感,但是,這種快感來得快也去得快,焦慮並沒有消除,甚至因爲知道的東西多了更焦慮了。

學習的目的應該集中在解決問題,並且爲了解決問題進行深度思考,直到問題解決,大學裏學好基礎學科就很好了,加油~


儘管我們不需要學奧數,但奧數訓練的思路,與算法訓練的思路是有共同點的,也就是【內化】這個事。

那,具體怎麼【內化】呢?

關鍵要練習更高層次的推理,不要停留在淺層。

這就意味着做題一定要慢慢加難度,不要搞低水平重複。

學了這一層,把這一層當做默認信息,上高一層。

在高一層運用熟練了,再把那一層當做默認信息,再高一層,水平得這麼練。

大多數人初學數據結構的時候(新手),會特意只做相關的練習,首先是讓自己知道這個東西。

類似於知道 “三角形內角之和等於180180度” 這條知識,我們會去找這樣一道題。

已知一個三角形,其中倆個角分別是 30度、60度,第三個角是多少度?

這種相關題,能迅速用上剛剛學的數據結構,但這是比較低的一層。

初學數據結構的人理解是,哪個結構對應哪種數據關係。

大多數人學過數據結構後(老手),會特意的問題儘量往數據結構偏移,主動製造一個局面 — 會通過一系列的佈局引導,把局勢引入自己擅長的局面。

類似於知道 “三角形內角之和等於180度” 這條知識,不過它不僅是一條知識,也是一個限制條件。

初學者知道的是:如果一個三角形的兩個角知道了,那就等於三個角也知道了。

而老手的人根本不需要【有意識地】去調用這條知識,TA們會主動創造這麼一個限制的環境,這個限制條件TA們會用,用的也特別好。

比如說,爲了全面確定一個三角形,他會探尋其中兩個角和一條邊的情況。

他想的不是這個公式是什麼 —— 那根本不用想 —— 他想的是我現在缺少什麼關鍵條件,如何得到這個條件。

我和別人下軍棋的時候,一開始根本不注意規則,倆個人玩起來也沒什麼規則…

後來,我發現利用好規則簡直是利器,於是我說了一條規則:最小的棋子才能奪旗。

他對我定的規則沒什麼反應,我就怕他知道我心裏的小九九,仔細觀察後,發現他對自己的棋藝充滿自信,對我的這條規則完全不在意(是一個會下棋的老頭子)。

規則結合我的戰術,就是把所有小棋(團長以下的)全部擺最前,主要是送死,全部給他。

因爲我們只有倆個人下,沒有中間的裁判,所以我也知道他那些吃了我小兵的棋子是什麼。

我獲取了大量的信息,消除了大量的不確定性,他的棋子在我眼裏我差不多都是明棋;而我的棋子他一點都看不明白,中場的時候我把炸彈放到他那邊,他應該以爲是一個小兵吧…不過保險起見,還是用司令來喫我的“小兵”(炸彈),不得不說他很謹慎,難怪對我的這條規則完全不在意。

最後在雙方都知道對方的軍旗時,他的棋子愣是不敢過來 — 我最小的剛好和他最大的一樣大,不過我只有幾個棋子,而他的有十幾個。

就因爲多了一個限制條件,解決問題的視角就多了一種。

  • 新手階段,主要是在刻意的局面下,刻意用那些知識;
  • 老手階段,因爲那些知識已經融入到了潛意識(變成了默認信息),主要是在刻意的製造一個有限制的局面;

學了這一層,把這一層當做默認信息,上高一層。

在高一層運用熟練了,再把那一層當做默認信息,再高一層,功夫得這麼練。

無論是武術,還是編程,功夫越高,要求越嚴!

而頂級的 ACMer,對信息的掌握還要高一級。

題目在他們眼裏,都是信息、信息的填充。

問題就是這麼一個問題:

  • 我已經知道什麼信息
  • 我能填充題目上的什麼信息
  • 哪裏是確定的哪裏是可變的,一目瞭然。

TA們根本都不用有意識地去想什麼“因爲……所以……”這種推理步驟,TA們眼中只有信息。

TA們都知道哪一步是必走的,哪一步是可選的,自己面臨哪些選擇,其中每一個選擇會導致什麼樣的局面,每一個局面對自己是好是壞。

棋盤上最終出現的局面,只不過是他腦子裏對這盤棋假想過的無數個局面中的一個而已 —— 那僅僅是信息。

因爲競賽題裏有精妙的技巧、深刻的思想,不僅能讓 playerplayer 體會到 010、1 世界的正宗趣味,而且可以讓 playerplayer 看見別人看不見的隱性信息。所以,高水平的解題訓練可以讓 playerplayer 學會十層的推理,而有的 playerplayer 只能推一層。

高水平的 playerplayer 總是稀缺的,不僅是在算法訓練上,在各個領域都是如此,高水平的 playerplayer 可能是軍師、國師、丞相、元帥,其實都是一層一層練習出來的呀。

方法:做編程練習題,如同遇到一扇被鎖着的門,您應該去哪裏找鑰匙呢?

顯然不應該只盯着鎖頭看吧,您得把注意力從問題本身轉移開啊,之所以打不開這扇門是因爲鑰匙並不在鎖孔裏,而是在別的地方。

  • Step1Step1-我已經知道什麼信息:徹底理解問題,但別找太難的,或已經會的。

用自己的語言重新表達問題,要求解的是什麼?已知什麼?要滿足哪些條件?


  • Step2Step2-我能填充題目上的什麼信息:形成解題思路,主要靠經驗和工具。

以前有木有見過相似或相關的問題?以前用過的方法這次是否適用?

不相似的地方是否可以引入輔助限制?條件有木有用足?

能不能構造應該比現在更簡單一點的問題,先解決簡單的?

如果微調已知的條件,甚至改變求解目標,能否找到解題線索?

這些問題,您需要反覆的問題,形成肌肉記憶,要背的這東西。


Step3Step3-哪裏是確定的哪裏是可變的,一目瞭然,核心在於總結。

絕不能解決完問題就了事,那就浪費了鞏固知識和提升技巧的機會。你再檢查一遍論證過程,嘗試用另外的方法解題,尋找更明快簡捷的方法,還要問,這次的解法能否用來解決其他問題?

這種解題方法在計算機科學裏叫【啓發式方法】,主要源於每個人的經驗、之前的算法思想(視角),啓發法本質上就是向經驗學習,拆解經驗中的規律和套路爲當下所用。

而總結,是最好的啓發時刻。

在《嚳哲》的學者存在性定理中,我們通過玩一個小遊戲,明白對任何一個問題,都存在一個能讓答案一目瞭然、脫穎而出的視角。

一道難題擺在面前,可能當前誰都不知道怎麼解決,但是您要相信,總有一個視角,會讓答案看上去那麼簡單,能夠脫穎而出。

視角,決定了問題的難度;也許普通人和大神差的只是一個視角及尋找視角的方法。

世界的規律在形式上並不複雜,但沒有一個恰當的視角只會看得很複雜,因此尋找這視角反而是一個複雜的事情了。

啓發式還有四種通用的套路:

  • 類比啓發式:通過聯想尋找事物之間的聯繫和共同點,獲取啓發;
  • 貪心啓發式:通過尋找當前局面最優解,獲取啓發;
  • 退火啓發式:在貪心啓發的基礎上加上隨機的探索,尋找到某個時刻時,停止探索,轉爲貪心啓發式;
  • 進化啓發式:隨機模擬生物(適者生存法則),留在最後的就是最優的;

新手、老手和大神之間的差異:

  • 新手階段,主要是在刻意的局面下,刻意用那些知識;
  • 老手階段,因爲那些只是已經融入到了潛意識(變成了默認信息),主要是在刻意的製造一個有限制的局面;
  • 大神階段,都是信息(不僅看見能看見的,還能看見看不見的),各種信息之間嘗試排列組合,就會形成很多方案。

除了刷題這個動作之外,

  1. 自己嘗試:一個問題琢磨 121-2 天都是正常,提升能力的上策:貴精不貴多,下策:貴多不貴精
  2. 有思路,編出來:面對 bugbug 不輕言放棄。邏輯都有了,爲什麼不能編出正確的代碼,肯定可以的!
  3. 揹着寫:看別人的解決方案,自己試着實現,一個題目刷倆、三遍是很正常的
  4. 得總結:思考、吸收別人解決方案中的優點,反思自己的代碼的問題。爲什麼別人的代碼可以更有效率或者更加簡潔?哪些是自己忽視的?

大神就是這麼一級一級訓練出來的,學了這一層,把這一層當做默認信息,上高一層。

在高一層運用熟練了,再把那一層當做默認信息,再高一層;功夫就得這麼練,而且功夫越高,要求越嚴

那怎麼才能突破瓶頸,達到【大神】階段呢?

這個就得在《模型》裏說了。

攻略,最後倒是變成了一個能力管理問題了,所以您需要一個教練。

訓練的甜蜜點是 85:1585:15,每一個新知識都是建立在舊知識的基礎之上。最好這一講中 8585% 的操作是您本來就會的(有親切感),1515% 是新技巧。

當然,這是最理想的情況。

有時候我們接受的會是 8080%新信息,這時候怎麼辦呢?

通用的方法是分多次死磕,一開始會感到很艱難,但堅持下來就好像吃了糖一樣。

因爲人有時候比較自戀,喜歡全能感,學習一個東西、做一個事情我一定要一次性過,這樣會顯得自己的厲害乃至偉大…如果分成倆次或者多次,那就會想:這麼一件小事,偉大如我,居然要分成倆次才能完成這件小事,這怎麼可以!!

生活中這樣的例子比比皆是:

  • 搬倆次比較合理的時候,卻只搬一次…更大可能是弄巧成拙;
  • 還有 “我不會再說第二次”…與別人交談吧,如果不能讓別人理解您的意思,那在是浪費雙方的時間;
  • 完美主義…

所以,自戀的人做起事情是不願意一次又一次的嘗試的,因爲失敗後,會有破壞 TA 的自戀。

自戀的人 TA 一定要一次性完成,要是沒做好,反而更會猛烈的批評自己。

那怎麼破呢?

最好是我們對自己既沒有積極期待,也沒有消極期待;既沒有表揚,也沒有批評,頭腦只是用來分析認識事物,而不去評判好壞對錯。

頭腦的認識,只是爲了幫助身體和潛意識的自我,更能放鬆和專注。當你能夠做到這一點,您的能力發揮,是最驚人的。

訓練的甜蜜點是 85:1585:15,每一個新知識都是建立在舊知識的基礎之上。

最好這一講中 8585% 的操作是您本來就會的,1515% 是新技巧。

如果是自學,因爲沒有基佬幫忙規劃,通常面臨的是 8080%新信息,這個時候我們和別人相比,最不缺的就是【意志力】這東西,最缺的是【效率】。

如果我們可以不在意【自戀的情緒】時,我們就能不斷的付出意志力,它是您最容易得到的東西,您可以以此來換取效率。

8080% 的新信息,我第一次嘗試能減少到 6060%,去休息等狀態好了,我立刻從頭再來,失敗是成功之路上所必要的,除非你失敗,否則你不知道自己的脆弱之處。

其他事情儘可以自戀,但在學習這件事情上,自戀可就學不到東西了,失敗就是失敗了,不要嚴重的攻擊自己,而是去安撫自己,並且在客觀事實中總結原因,而後再次嘗試,這樣就可以了。


如果您想參加競賽甚至一年內拿到亞洲賽區的冠軍,那每天學習四小時,我想您的安排最好是這個配比,每天學習效率的上限也就是 15.8715.87%。

訓練,貴精不貴多。事實上,這種刻意練習,很難保持在 22 小時以上。

每天精力最充沛的時段拿出來訓練自己,這段時間是您每天最重要的總結,是最值得分析的。

精力不那麼集中的時候,去看比較輕鬆的知識,比如:

  • 讀理財、文化、歷史、英語、文科、商科方面;
  • 運動,洗澡,社交,處理好日常事務;

最好是跟着教練走,因爲教練不僅能規劃訓練的層級,也能在競賽前夕把選手的身體、心理調整到最佳狀態。

擴展閱讀 —> 請猛擊:《系統性學習》。

 


模型:一題多解怎麼來?

OJ平臺上,我們貌似比較追求一題多解。

其實新手、老手做題最好是多題一解,不要學大神的一題多解。

雖然一題多解是很厲害,但多題一解、多解歸一對我們來說會更現實。

找到最優的算法太考智商了,我應該是不夠的,如果能把完全不同類型的題目,看作一種題目去解,對我已然幫助很大;如若能把不同問題的解法,變成一種解法,那應該是抽象到最底層的方法論了。

建立自己的工具樹,不斷的掛果子,收穫的也是知識。

相比之下,做那些只涉及到具體的問題,就算做很多,遇到新問題還是沒法解決。

如果學會把具體問題抽象成模型,就能解決更多更難的新問題。

無論是【數據結構】,還是【算法思想】、【設計模式】,這些通用的方法,是人們在設計程序時,都總結出的經驗。

這些經驗是具體的慢慢演變爲抽象的,從具象到抽象化並傳承這些抽象的知識、經驗,是人與其他動物最大的區別。

大神不也都是在抽象這方面掌握的特別的好嘛?

這種抽象的模型多了,自然能做到一題多解。

我們已經知道了大神爲什麼這麼牛,但從老手到大神之間還有很多坎的。

 


應用:如何把問題與某個抽象的模型相連?

比如,如何把問題與某個抽象的模型相連?

也就是,抽象還原爲具象。

具體怎麼做呢,我們來看一個歷史性的問題,這是一個讓醫生們束手無策的問題。

以前有一種射線,只要以一定的強度照射在腫瘤上,就能把腫瘤給殺死,等於是可以用來治療癌症。

現在問題在於,射線到達腫瘤之前肯定會先接觸到患者身體的其他組織,那就會把好的組織也給殺死。

可是如果把射線強度調低一點,好的組織能不被傷害,可是對腫瘤就也沒用了。

那有沒有一個什麼辦法,不用做手術開刀,既能讓射線殺死腫瘤,又不會傷害其他組織呢?

儘管他們已經有了這麼好的工具,但卻不知道該怎麼用~

就設計而言,這個答案本身並不重要,我們關心的是尋找答案過程中使用的思維方式。

有抽象纔有 “類比”,用類比還原抽象問題,是把一個領域的思想,運用到另一個領域中去,不過您得先發現倆個領域的共同點。

從前有一個將軍,要攻打一座城。攻城需要很多士兵同時發動進攻纔好。可是這座城周圍的道路都很窄小,並不適合大軍通過。

這怎麼辦呢?

將軍知道通往這座城的道路有很多條,於是他把士兵分散開,以小隊的形式從不同的道路出發,按照約定時間一起到達 — 結果就把城給攻下來了。

類比解決問題,是把一個領域的思想,運用到另一個領域中去。

醫生們的問題,也可以用若干束低強度的射線從不同的方向照射腫瘤。

因爲射線強度不高,所以不會殺死途中路過的身體組織;而因爲在腫瘤上匯聚的多個射線加起來的強度夠高,所以能殺死腫瘤。

其實這就是現在有不少醫院使用的“伽馬刀”。

一般人看東西是關注不同點,而高手、抽象思維則善於發現兩個很不一樣的事物之間的相同點。

比如,下面這六件事情,您能不能把它們給分個類 ——

  • 經濟泡沫
  • 北極冰川融化
  • 美聯儲調節利率
  • 人的身體出汗
  • 不同的商品相繼漲價
  • 大腦指揮身體做動作

對美國西北大學的學生測試表明,如果是按照學科分,所有學生都能分的很好。

1、3、5 是經濟學問題,4、6 是生理問題,2 是自然環境問題。

但要是按照這些事情的內部機制分類,就只有少數有跨界學習經歷的學生能分好。

  • 事實上 1 和 2 都是增強迴路(因增強果,果增強因)

買東西的人越多經濟越好,經濟越好買東西的人越多;冰川越融化吸收陽光越多,吸收陽光越多冰川越融化。

  • 3 和 4 都是平衡迴路(因增強果,果減弱因)

美聯儲加息防止經濟過熱;皮膚出汗防止身體過熱。

  • 5 和 6 都是連鎖信號傳遞(因果鏈)

石油漲價導致日用品漲價;大腦神經信號傳遞到四肢

能看出這種深層思維結構,才談得上舉一反三。

如果沒看出來,其實也沒關係,因爲增強迴路、平衡迴路、因果鏈是【系統動力學】裏面的模塊,其地位等同數據結構的線性表、樹、圖。

數據結構是對數據關係的抽象,和系統動力學一樣,都適用於解決有一定規律的重複性問題。

不過數據結構解決的是,數據儲存和數據調用方面的問題,屬於單純的問題(有明確的方向、有標準的答案),大部分技術問題都是單純問題,您掌握的工具、模型、視角,以及您是否聰明決定了您解決問題的上限。

而【系統動力學】雖然也是解決問題的,但這種問題不是單純的問題(有明確的方向、有標準的答案),而是倆難問題(不好取捨)、棘手問題(對於無解的問題,也有應對的方法),比如 商業難題、看透和管理人心、預測未來等等。

系統動力學】和【數據結構】也是有交集的,圖論是數據結構的精神,也是系統動力學的靈魂。

但是一般大學生並沒有這種深層的思維結構,他們只知道自己親身經歷的事情一樣,只理解自己專業的一點知識。

有研究說,一般科研工作者的業餘愛好水平跟普通老百姓沒啥區別。

但是學術水平越高的科學家,就越有可能在學術工作之外發展個什麼業餘愛好 —— 而諾貝爾獎得主有諸如演員、舞蹈家或者魔術師之類業餘愛好的可能性,比一般科研工作者要高……2222 倍。

類比可以讓我們舉一反三,類比可以啓發我們創造新事物,類比可以讓我們審視自己和別人的原則,類比可以幫助我們發現各方的分歧所在,類比可以幫助交流思想……

從具象到抽象,需要抽象思維;從抽象到具象,需要類比與聯想。

抽象思維能讓您認識到事物的本質,發現各種看似不一樣的事物背後的共同點;類比的背後,是高級的抽象思維。

 


總結

我說起來容易,但編程是一門硬技能,需要系統性的勤學苦練才能學會。

所以,推薦您聯機學習,不要單機打怪。

雖然夥伴也只是在“在黑暗中並肩行走”,所能做到的僅是各自努力追求心中的光明,並相互感受到這種努力,相互鼓勵。

但這種相互鼓勵的圈子裏,讓我知道你一直與我同在,你讓我平靜,讓我對自己感覺更好。


刷題也是一件很有意思的事情,如果沒什麼功利性的話(能打破所有對結果的預設期待,打破期待,關注練習本身)。

編程練習和別的事不同,要是解對了,自己能夠知道,也會很開心。感覺自己的智慧就取得了一點實在的成就,雖然這種成就可能微不足道,但對個人來說,這些成就絕不是毫無意義的。

相對的,要是解的不對,自己也知道沒解出來,就會有點小鬱悶。

編程練習未必能培養我們什麼能力,實際的好處可能就是修身養性,純粹玩玩也是挺好的,把刷題當成強身健體陶治情操的活動吧。

正如喬恩·卡巴金說的:

你的態度就像是一片土壤,練習,就是你在這片土壤上培育一份能力,讓心念平靜、身體放鬆、集中注意力、看的更加清晰。

如果態度是這片貧瘠的土壤,也就是說,如果你對練習的承諾和投入很低微,那麼,你就難以持之以恆的發展出那份平靜和放鬆。

同樣的,如果土壤被污染了,也就是說,如果你帶着強烈的預期去練習,比如強迫自己去感到放鬆,強求達到某種目的,那麼這片土壤將是不毛之地,你也將很快得出刷題是沒有用的結論。

很大程度上,我們帶到練習裏的態度,將決定它對我們長期的價值。

這份態度,不僅僅可以用在練習這件事上,生活也可以噠~

… …

 


第一級【編好程序】

這是計算機從業者所必須掌握的,屬於“雕蟲小技”。

(P.S. 這是清華全球創新學院的創院院長史元春教授說的,這話要我說出來,估計會被各位大佬吊打)

【過關條件】:學完編程語言,每學一章都有做三道編程方面的練習。

文章 + 視頻 + 題目

 


第二級【儲備模型】

在《數據結構》、《算法思想》、《設計模式》裏有大量的模型。

數據結構的出現和計算機本身工作的方式有關。

今天演化出來的很多數據結構,甚至和圖靈機的原理,以及計算機底層的馮·諾依曼結構也有關。如鏈表這種數據結構,就和圖靈機的設計直接相關。

世界上很多抽象化的結果,都和我們人容易掌握的工具有關。

如我們將大部分零件做成圓形的,或者有圓形的切割和開口,主要是因爲圓形好加工。我過去做過金屬工藝的加工,非常能體會使用機械(比如車牀)切出一個圓的東西是很容易的事情,但是要切出一個方的是極爲費勁的。

因此,誰要是在機械設計時搞了一堆方的設計,會被認爲缺乏基本的機械設計素養。如果您到製造業的工廠去看看,基本上就只有兩種運動,直線運動和圓周運動,其它所有的運動都是它們的組合(而且用得並不多)。

這並不是說世界上只有這兩種運動,但是將運動抽象成這兩種,就容易在機械中實現了。

順序存儲的數組、鏈式存儲的鏈表也是如此。

與《算法訓練》配套的數據結構索引:《數據結構從哪開始


【過關條件】:

所以要對常見的算法有一定的基礎:

  • 常見排序(冒泡、快排、插入、堆排、歸併…)

  • 雙指針(快慢指針、左右指針)

  • 貪心、二分(二分查找)

  • 搜索(dfs、bfs、各種剪枝、回溯思想)

  • 動態規劃(各種子序列、各種子串、常見的那幾個揹包問題)

  • 前綴和

  • 樹的常見操作(各種遍歷、各種樹的性質、最小生成樹)

  • 圖(最短路、常見性質)

常見的模型較爲了解之後再去【第三級】:

  • 常見數據結構和集合類(鏈表、隊列、棧、map、list、set、並查集都得會用)

這些基礎知識不求精通,不會寫代碼都行,但總得知道這些知識咋回事。

 


第三級【解決問題】

OJ訓練:題目如何安排》,如果想在這個階段比較舒服、高效,就得找甜蜜點安排每天的題目,因材施教。

做相關的題:按類別 -> 畫圖分析增刪改查的動態過程 -> 手寫代碼 or 手敲 -> 對比題解 -> 揹着敲。

廣泛涉獵,一本一本書地學,一個一個知識點的認真總結,從長遠來看,纔是真正“高效率”的學習方法。

如果想未來是一個深不可測的計算機專家,在21秒鐘或24小時內改變自己的人生,或者提高自己實際的編程水平,這是不可能的。

您得試試連續24個月不間斷的努力提高自己,這離不開春去秋來的勤奮。

【過關條件】:

  • 一年裏,每天做題刻意練習 2h

  • 飲食作息規律,要早睡才能早起,而早睡的條件是比較累,所以您可以每天負重深蹲 100 個,而要想運動表現處於好狀態,您得多喝溫水…

  • 積極,推薦閱讀《積極達成:處理好情緒再處理問題》,智商特別高的人,情緒不太能影響TA

一個人要垮,首先精神先垮,只要精神不垮,就沒有任何力量能摧毀我的意志和身體。

                                                                    --- 某位大佬說的

 


第四級【建模能力】

抽象還原爲具象的能力,打比方其實就是知識遷移的能力,一個人理解倆件事情的本質(還找了共同點),才能比方得讓人拍案叫絕。

從具象到抽象:抽象思維

從抽象到具象:類比聯想

抽象思維、類比聯想相輔相成。

【過關條件】:

閱讀,讀完後認真做筆記。

  • 抽象思維:波利亞三卷《怎樣解題》、《數學的發現》、《數學的猜想》

  • 培養類比能力的書籍:《The Art of Logic in an Illogical World》、《創新的本能:類比思維的力量》、《百科全書》

儘管閱讀真是一件很有意思的事情,但我自己也有一個體系:日閱讀量 143 頁。

如果僅就閱讀而言,應該以“閱讀時長”爲標準是最好的。

  • 有這樣一個規律:對同一個人來說,收穫新知識的多少正比於閱讀/學習的時長。

因爲一個人的理解力和智力是穩定的,所以不論囫圇吞棗的快看,還是細嚼慢嚥的慢看,單位時間裏收穫的知識總是大致一樣多的。

無論是啃技術書籍,還是用在許許多多方面,每種都淺嘗輒止,只要您持續花時間,最後的效果都很好。

 


第五級【優化模型】

如果有一天,自己可以優化模型,甚至挑戰這些模型,您的編程水平就很高了,也就是培養建模能力,首推《系統動力學》。

  • 培養洞察力能力的書籍:《Thinking in Systems: A Primer》、《如何系統思考》、《系統思考》、《第五項修煉》

系統動力學主要解決問題的,但這種問題不是單純的問題(有明確的方向、有標準的答案),而是倆難問題(不好取捨)、棘手問題(對於無解的問題,也有應對的方法),比如 商業難題、看透和管理人心、預測未來等等。


如果我們拋棄次要因素,專注主要的趨勢,那工程師可以分爲五級,第五級最多,第一級最少(中國還沒有一級工程師)。

如果只盯着眼前的事情,一段時間後自然覺得自己啥都懂了,但其實還有一個更大的世界,更高的層次需要我們去認識。但這不僅是一個增強技術能力的過程,更是轉變思考方式,擴大眼界的過程。

工程師列傳:

  • 一級工程師:高德納Google雲計算髮明人 (愛迪生、貝爾、福特)

  • 二級工程師:傑夫·迪恩發明Google大腦、鄧峯打造出了真正意義上的網絡防火牆

  • 三級工程師:自己的產品做到世界第一,如人臉識別第一、語音識別第一等等

  • 四級工程師:有頭腦的工程師,能寫出大型的軟件項目的軟件工程大師

  • 五級工程師:比工科大學畢業的大學生強一些,更有經驗

【編好程序】、【儲備模型】、【解決問題】、【建模能力】,是圖中第五級工程師的能力,而【優化模型】是圖中第二、三級的工程師的能力。

第一級工程師,在玄幻小說裏,也是傳奇人物了。

比如《斗羅大陸2絕世唐門》的主角[霍雨浩],創造了人類與魂獸新的連接方式併成立了組織傳靈塔,消除了倆大種族日益加強的爭端…

正是開創了一個產業,這個人的影響力也會波及到後世,不僅可以影響身邊的人,還有影響到未來的人們…


現在的培訓班、按部就班教學的大學、網絡上的課程,大多是教授 “計算機系” 最基礎的內容 — 技術。但這些還都是比較淺層的計算機內容,只會這些在現代只會被代替… …

就像很多人說做 IT 是喫青春飯,從現象上看,確實如此。這裏面很重要的原因在於,很多人在學習計算機時,以爲自己所學的就是熱門,自己就是中心,但其實只是掌握了一種服務於他人的工具而已。

因爲很多人學了就只會操作這個工具(只會寫代碼),而操作它做什麼,則完全需要別人下命令。

如果一個人只會使用編程這個工具,很快就會被更年輕的,更會操作工具,而且掌握了新工具的人取代。

算法訓練,其實是在訓練一種新的認知,一種信息時代的思維方式:計算機思維

雖然它也是人思維的一部分,但和常人的思維方式完全不同,是伴隨計算機出現的,結合人的邏輯、數學思維的思維。

訓練好這種思維後,就是要把這種思維方式用到其他學科領域中去,可以帶給人、產業的認知升級。 最需要考慮的一個問題就是,如何把那個領域的問題轉化爲信息或者數學問題,這也正是大部分計算機科學家做的事情。

比如一些,近些年大名鼎鼎的技術:

  • 語音識別。

    科學家會先去了解人類是怎麼識別語言,怎麼發音的。

    以前的專家系統研究的都是表象,想的是語言學的各種概念:元音(聲母)、輔音(韻母)、詞組、語法、上下文… …這些都是表象,或者說是我們人爲創造出來的概念。

    語言只是承載信息的工具,或者說是一種編碼方法,而背後的信息纔是最重要的。

    我們通過說話,即口述語言的表達,是爲了讓收聽者,明白我們腦子裏想的意思:

    1. 說話人將意思用語言描述出來
    2. 聲音在空氣、水、電話線中傳播,收聽人將聲波變成耳朵能夠接受的信號,通過聽覺神經傳到收聽的大腦裏
    3. 收聽人將收聽到的信號還原回講話人的意思

    第一個過程,其實和通信中的信息源編碼過程是一致的,您在微信中發一條消息,計算機先要將它變成能夠在通信系統中傳播的編碼,這就是編碼過程

    第二個過程,其實是信息在不同信道中傳輸的過程。

    第三個過程,則是第一個過程的逆過程,即解碼過程

    編碼-信道傳輸-解碼,這不就是一個標準的通信過程麼?既然語音識別的等價問題是通信問題,那麼就可以採用解決通信問題的方法解決語音識別問題… …

    信息處理的問題是數學問題,讓計算機處理自然語言也是數學問題,看似需要人腦推理的問題,其實是一個計算問題。

    所以,賈里尼克教授開玩笑的講,他每解僱一位語言學家,他的語音識別系統的錯誤率就降低 11%。
     

  • 機器翻譯。

    再接下來,賈里尼克教授的一個叫 彼得∙布朗 的部下發現機器翻譯的問題也是一個通信問題。

    布朗是這麼考慮的:

    1. 假如我們要將中文翻譯成英文,我們通常認爲說話人說的是中文。但是布朗換了一個角度看問題,他覺得當你對一個外國人說話時,說的是一種可以用英文表達的意思,只不過你在表達這個意思的時候,選擇使用中文做了一次特殊的編碼而已。
    2. 翻譯者,也就是解碼的一方,所要做的無非是把中文編碼的信息串解碼還原成你的(英文)意思。這麼看待問題,就把機器翻譯問題從兩種自然語言的理解,變成了一個通信問題。

    信息處理的問題是數學問題,讓計算機處理自然語言也是數學問題,看似需要人腦推理的問題,其實是一個計算問題。
     

  • 基因測序。

    後來,到了 9090年代的時候,約翰∙霍普金斯大學的 薩爾茲伯格 教授採用了一個全新的視角來看待基因測序問題。

    他認爲:

    • 人的基因不過是一本特殊的書,書中的字母只有 AGCTA、G、C、T 這四種,因此任何識別語言文字的算法,比如語音識別和 OCROCR 的算法,都可以用於基因測序。

     
    有了這個想法後,他離開了大學,到專門從事基因測序的研究所 TIGRTIGR,轉行從事基因測序研究了,並且後來獲得了那個領域的最高獎。

    信息處理的問題是數學問題,讓計算機處理自然語言也是數學問題,看似需要人腦推理的問題,其實是一個計算問題。

     

  • 股票市場的分析和預測

    2016年,文藝復興科技公司 被譽爲 “世界上最大的搖錢樹”,因爲這30多年以來,這個基金平均每年的增幅都在 8080% 左右。

    創始人西蒙斯有一個獨特的投資座右銘:

    • 一旦確定好了一套算法或者模型,那麼就百分之百地相信它,不去對它進行任何人爲的干擾,直到它給你帶來最終的結果。

    這麼多年來,西蒙斯都堅持着這條專屬於他的座右銘。

    西蒙斯的管理類似賈里尼克教授,比如他請的人,有物理學家、天文學家、數學家等等,卻偏偏沒有金融家。

    因爲西蒙斯認爲,數據分析必須要基於非常乾淨的數據處理,以及最先進嚴謹的算法,而金融理論跟經驗並不是他最需要的。

    當西蒙斯 7171 歲選擇退休的時候,他把公司的管理權交給了兩位語音識別方面的專家。

    看起來,語音識別對沖基金是兩個跨度非常遠的行業了,但是在西蒙斯看來,語言是一種非常具有預見性的系統,他相信他請的這兩位語音識別專家,可以把他們的語言研究技能運用到金融市場上去。

    這個語言研究技能不是語言學的方法,而是身爲計算機科學家的計算機思維

可以說,計算機系最有前途的學生一定是跨學科的 ,利用計算機思維解決那個領域的問題,當然對那個領域的知識也是要懂的。

  • 比如做語音識別,計算機還真的只是個工具,對於聲學的瞭解,對於信號處理的瞭解,對於自然語言處理的瞭解,構成了從事這個領域研究的必要條件。瞭解這些,你就可以做研究,發明新算法,成爲領域專家。不瞭解這些知識,只能當一個幫助別人寫程序的程序員。

因此,計算機實際上是一個十分跨界、注重組合的學科;與計算機聯繫的領域,就像四面八方的窗戶… …但對於計算機科學家來說,己身最核心、最基礎的技能莫過於計算機思維

如果單純的把計算機單純當作實現自動化、提升生產率的工具、一份工作,你就無法深入研究計算本身的邏輯,就無法get到計算的真正魅力,更無法理解深藏於宇宙中的、具有通識意義的計算道理 —— 最終無法獲得計算背後、提升效率的心法真意!

反之,如果你不去刻意追逐自動化和效率、工資,另闢蹊徑研究計算的問題,研究計算機存在背後的原理,明白人腦的計算邏輯、自然界的計算方式、宇宙的計算公式,那麼計算機世界核心的寶藏就會爲你敞開,你會找到最至高無上的效率之法!

您想選哪一種都取決於您自己的勤奮、眼光和思想~

 
 
 
 
 
 
 
 
 
 
 
 


有的時候,我們是在聊算法,有的時候是在拿算法說事。

  • 數據結構》:解題爲主,刷題背題型,收集模版
  • 算法訓練》:總結爲主,計算機思維,就靠推理

 

我有試着每天總結,這樣可以不受某個具體的教育環境限制,自己培養自己(天才就是這樣吧)。

總結的初心很清晰:

  • 爲了可以不遵守任何作息規則,又生活的自律。
  • 爲了安頓自己,特別是安於自己的笨拙、孤獨。
  • 爲了讓玩遊戲、看小說、煲劇、浪費時間、虛度光陰有一種合法的感覺,也能進入看似慢騰騰的體驗,享受了過程。還去影響了每一個日子的品質。
  • 爲了自己做的每件事都有意義,不做沒有意義的事。

但發現,真正的收穫還不是這些,而是一種通用的認知的能力

自己的思考與思路越來越接近於正確、越來越完整、越來越高效……

如果不斷加強自己的 認知能力,也許終究有一天,哪怕是你不假思索、甚至隨隨便便創造出來的東西,都是真正有價值的,不僅對自己有價值,對他人也有價值,對很多很多人有價值,甚至對絕大多數人都有價值……

可能,算法訓練的背後也不是學了具體(抽象)的算法、題型,而是一種認知能力,一把打開所有知識的萬能鑰匙

文字以及文字所闡述的道理,背後是作者的“思考方式” ,作者的“思考方式”與自己的“思考方式”之間的不同,以及,若是作者的“思考方式”有可取之處的話,自己的“思考方式”要做出哪些調整?

於是,一本高數讀完,大多數人就是考個試及格,而另外的極少數人卻成了科學家——因爲他們改良了自己的思考方式,從此可以“像一個科學家一樣思考”……

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章