到底該如何學習演算法?

2021-06-01 00:09:56 字數 1069 閱讀 7567

很多人學習演算法都特別重視**,不管是偽**也好還是具體語言**也好,然而我認為**不是那麼重要的,即使書上只有**你也不能只拘泥於**層面,而是應該通過逆向去弄明白這個演算法到底是怎麼回事,而不能停留在程式執行過程這個表面上。實際上,如果我告訴你乙個演算法的大體思想,你自己寫出實現**應該是不成問題,而記住思想總比記住**要容易得多,而同乙個思想也可以用於其他問題的解決上,相比之下,**的價值就遜色很多了。

就拿大家都知道的快速排序來說,快速排序的核心在於其partition函式,《演算法導論》既給了偽**,又畫了執行過程,最後給予了證明,看似有些複雜,實際上這個演算法還是很容易的。

我最初看了partition函式的偽**和執行過程後,僅僅停留在感性認識上,所以只是憑著感覺記住了程式的執行過程,並且能夠根據這個過程聯想到實現**,但是隨著時間的推移,也漸漸淡忘了。後來一天我突然領悟到,partition函式並沒有我想象的那麼複雜,它的思想很簡單:用兩個變數i和j,i就像一堵牆,從陣列的起始位置(這裡設定為0)到i這個位置(包括i)的所有元素都是小於pivot的,我們把這些元素組成的集合起個名字:a,而j從頭開始掃瞄,如果發現有符合小於pivot這個要求的元素,就把它放到集合a中,怎麼放呢?先把i這個牆向後移動一位以增加集合a的大小,然後把這個元素和i指向的那個元素交換即可,這樣迴圈下來就保證了集合a中的元素都小於pivot,最後把pivot放到集合a後面就把陣列劃分成我們想要的那兩部分了。

再比如說全排列問題,如果你給乙個完全沒接觸過全排列問題的人一段輸出全排列的遞迴程式的**,那麼十有**這個人除錯半天也不知道這個遞迴過程到底怎麼回事——因為他已經被這個執行過程給搞糊塗了。相反,如果你不告訴他**而是先給他講解一下全排列演算法具體是怎麼回事,那麼他也許自己都可以寫出**。

可見,如果只看偽**和程式的執行過程,不做深入**,也只能停留到感性認識的層面:腦中只閃現著乙個不斷變化的程式執行過程,而不能到形式化層面,更準確地說,不能達到數學的高度上,追根溯源,數學還是起到了舉重輕重的作用。在此,引用豆瓣上的一段話來結束本文(來自:對演算法的學習也要從問題本身的數學結構入手,理解解決此種結構問題的演算法它的設計思想,掌握分析具有各種結構特徵的演算法的數學工具,學習怎樣發現問題的結構並從中推出問題的下界(lower bound)。這些才是學習演算法的根本。

程式設計師到底該如何學習?

這篇文章只適合入門級的程式設計師。很多人都發訊息問我,有沒有推薦的學習 面試資料啊?哎,我只能說,cracking the coding interview leetcode以及leetcode論壇,topcoder等。可是,這真的適合你嗎?我真的不想做這樣不負責任的回答。因為每個人的學習方法應該是...

雲原生到底該如何理解

什麼是雲原生?我們已經進入智雲時代,雲原生這個詞在行業裡異常火爆。那麼到底什麼是雲原生呢?我們知道雲的目的是為了簡化交付 規模和管理,以推動創新。公有雲不僅改變了企業開展業務的方式,還改變了安全廠商營銷產品的方式,所以我們看到很多廠商都聲稱其要提供 雲原生 解決方案。但是,雲原生應該不僅僅是一種營銷...

Redis到底該如何利用(三)?

全資料增量同步 所謂全資料校驗,即所有的快取資料首先都同步至redis,然後根據資料的時間戳來進行同步。分解步驟如下 首先將快取的資料初始化,同步至redis和memorycache,保持初始資料的同步 第二步,每當操作了資料之後,給記錄乙個時間戳標識最近的更新。memorycache定時或者每次取...