【乾貨】動態規劃十問十答

專欄 | 九章算法
網址 | www.jiuzhang.com程序員

問1 動態規劃是個什麼鳥蛋?面試

答:動態規劃是一種經過「大而化小」的思路解決問題的算法。區別於一些固定形式的算法,如二分法,寬度優先搜索法,動態規劃沒有實際的步驟來規定第一步作什麼第二步作什麼。因此更加確切的說,動態規劃是一種解決問題的思想。這種思想的本質是,一個規模比較大的問題(假如用2-3個參數能夠表示),是經過規模比較小的若干問題的結果來獲得的(經過取最大,取最小,或者加起來之類的運算)因此咱們常常看到的動態規劃的核心——狀態轉移方程都長成這樣:算法

  • f[i][j] = f[i - 1][j] + f[i][j - 1]
  • f[i] = max{f[j] if j < i and …} + 1
  • f[i][j] = f[0][j - 1] && judge(1,i) || f[1][j - 1] && judge(2,i) || …

問2 動態規劃面試考得多麼?數組

答:多。而且愈來愈多。隨着CS從業與求職者的增長,並伴隨你們都是「有備而來」的狀況下,通常簡單的反轉鏈表之類的題目已經沒法再在面試中堅挺了。所以在求職者人數與招聘名額的比例較大的狀況下,公司會傾向於出更難的面試問題。而動態規劃就是一種比較具備難度,又比較「好出」的面試問題。相比其餘的算法與數據結構知識來講,貪心法分治法太難出題了,搜索算法每每須要耗費求職者過長的程序編寫時間通常也不傾向於出,二叉樹鏈表等問題題目並無那麼多,並且求職者也都會着重準備這一塊。所以動態規劃這一類的問題,便愈來愈多的出如今了面試中。微信

問3 動態規劃快在哪兒?數據結構

答:動態規劃通常來講是「高效」的代名詞,由於其解決的問題通常退而求其次的算法只有搜索了。以「數字三角形」一題爲例子(數字三角形link),在「三角矩陣」中找一條從上到下的路徑,使得權值之和最小。若是使用暴力搜索的算法,那麼需求窮舉出2^(n-1)條路徑(n爲三角形高度),而使用動態規劃的話,則時間複雜度下降到了n^2,完成了質的飛躍。那麼究竟爲何這麼快呢?緣由在於動態規劃算法去掉了「無用和重複的運算」。在搜索算法中,假如從A->B有2條路徑,一條代價爲10,另一條代價爲100,B->終點有1024條路徑。當咱們選擇了代價爲10的那條路徑走到B時,能夠繼續往下走完1024條路徑到終點,可是在此以後,咱們再從代價爲100的路徑從A走到B時,咱們能夠發現此時不管如何走,都不可能有剛纔從10的路徑走過來更好,因此這些計算是「無用」的計算,也能夠說是「重複」的計算。這就是動態規劃之因此「快」的重要緣由。學習

問4 學習動態規劃有什麼捷徑?優化

答:咱們將動態規劃的常見類型分爲以下幾種:code

  • 矩陣型
  • 序列型
  • 雙序列型
  • 劃分型
  • 區間型
  • 揹包型
  • 狀態壓縮型
  • 樹型

其中,在技術面試中常常出現的是矩陣型,序列型和雙序列型。劃分型,區間型和揹包型偶爾出現。狀態壓縮和樹型基本不會出現(通常在算法競賽中才會出現)。
每種類型都有着本身的題目特色和狀態的表示方法。以矩陣型動態規劃爲例,通常題目會給你一個矩陣,告訴你有一個小人在上面走動,每次只能向右和向下走,而後問你好比有多少種方案從左上走到右下(不一樣的路徑link)。這種類型狀態表示的特色通常是使用座標做爲狀態,如f[i][j]表示走到(i,j)這個位置的時候,一共有多少種方案。狀態的轉移則是考慮是從哪兒走到(i,j)這個座標的。而序列型的動態規劃,通常是告訴你一個序列;雙序列的動態規劃通常是告訴你兩個字符串或者兩個序列。
將所作過的動態規劃問題按照這些類別進行歸類,分析狀態的表示方法和狀態轉移方程的構造方法在每種類型中的近似之處,會讓你更快的學會動態規劃。cdn

問5 什麼樣的問題適合使用動態規劃?

答:可使用動態規劃的問題通常都有一些特色能夠遵循。如題目的問法通常是三種方式:

  1. 求最大值/最小值
  2. 求可不可行
  3. 求方案總數

若是你碰到一個問題,是問你這三個問題之一的,那麼有90%的機率是使用動態規劃來求解。
要重點說明的是,若是一個問題讓你求出「全部的」方案和結果,則確定不是使用動態規劃。

問6 解決一個動態規劃問題的步驟是什麼?

答:首先根據「問5」判斷是不是動態規劃的問題,若是是,則嘗試將其按照「問4」進行分類,找到對應的類別和類似的問題。接着從下面的4個要素去逐步剖析解決這道題:

  1. 狀態是什麼
  2. 狀態轉移方程是什麼
  3. 狀態的初始值是什麼
  4. 問題要求的最後答案是什麼

每一個步驟分析完成以後,就基本上解決了整道動態規劃的問題。

問7 怎樣優化動態規劃的時間?

答:通常來講,使用動態規劃求解的問題,時間上已經比暴力搜索要優化不少了。可是仍然存在着一些能夠優化的空間。一般來講,動態規劃的時間優化,有以下兩種常見的方式:

  1. 經過變換狀態優化
  2. 經過決策單調優化

對於經過變換狀態來優化的問題比較難,須要一些經驗和靈感。而對於決策單調的優化,則比較簡單,但適用範圍不廣,通常只適用於劃分型動態規劃當中,一般這個方法能夠將複雜度下降一個數量級。

問8 怎樣優化動態規劃的空間?

答:動態規劃的空間優化只有一種方法,就是使用滾動數組進行優化。以一個二維的動態規劃爲例子。假如狀態轉移方程以下:f[i][j] = f[i - 1][j] + f[i][j - 1]。咱們能夠發現,第i層的狀態,已經和第i-2層的狀態沒有關係了,那麼這種狀況下,用於存儲第i-2層的空間就能夠被重複利用。方法很是簡單,把數組的第一維對2取模就能夠了:f[i % 2][j] = f[(i - 1) % 2][j] + f[i % 2][j-1]。這種方法一般能夠將空間複雜度下降一個數量級。

問9 有什麼書籍和參考資料能夠推薦麼?

著名的揹包九講:
揹包九講link
(也能夠直接在網上搜索揹包九講)

問10 有哪些動態規劃題目必需要練習的?

在LintCode上包含了30餘道動態規劃的練習題,都是從實際的面試問題中彙總的精選練習:
動態規劃練習題link


歡迎關注個人微信公衆號:九章算法(ninechapter)。
精英程序員交流社區,按期發佈面試題、面試技巧、求職信息等

九章算法,IT教育領域的深耕者
相關文章
相關標籤/搜索