算法導論學習筆記之1--從LCS到動態規劃

作爲一個非科班出身的碼農,對計算機的一些基礎知識有很多不太熟悉的地方。考慮到萬丈高樓平地起,只是一味地在工作中對業務問題構建空中樓閣確實不利於以後的發展,決定對計算機的基礎知識做一些學習和整理,一方面檢查自己是否真正掌握該內容,另一方面望各位同行不吝賜教。

廢話少說,直入正題,今天主要整理一下動態規劃,以下內容主要來源於對《算法導論》和《麻省理工大學算法導論公開課》的學習整理。

1. 動態規劃簡介

動態規劃(Dynamic Programming)中的programming指的是一種表格法,直譯過來就是用動態表格去解決問題的一種方法,通常用來解決最優化問題,問題的解並非唯一解,而是一個解。沒有實例講解算法就是耍流氓,接下來以最長公共子序列的問題來展開介紹動態規劃是個啥,以及如何設計動態規劃來解決實際問題。

2. 最長公共子序列問題

子序列:給定一個序列 X=<x1,x2,...,xn> ,另一個序列Z=<z1,z2,...,zk> 滿足如下條件時成爲 X 的子序列,即存在一個嚴格遞增的 X 的下標序列 <i1,i2,...,ik> ,對所有的 j=1,2,..,k ,滿足 xi=zj
公共子序列:給定兩個序列 XY ,如果 Z 既是 X 的子序列,又是 Y 的子序列,那麼稱 ZXY 的公共子序列。
最長公共子序列(Longest common subsequence, LCS)問題即給定兩個序列 X(x1,x2,...,xn) , Y(y1,y2,...,ym) ,求 XY 最長的公共子序列。

問題實例

設給定兩個序列,X=(A,B,C,B,D,A,B)Y=(B,D,C,A,B,A) ,求 XYLCS
直觀地,我們可以考慮用窮舉法解決該問題。

2.1 窮舉法

因爲要查找 XY 中的公共子序列,因此,只要判斷任意 X 中的子序列 Z 是否也是 Y 的子序列即可。
時間複雜度:O(n2m) ,其中,O(n) 爲掃描 Y 所用的時間,2mX 中子序列的個數。該時間複雜度是一個指數型的,無法接受。因此考慮簡化該計算。

2.2 帶備忘的自頂向下方法

首先,引入一組定義:

Define:Thus:|s|=lengthofsc[i,j]=|LCS(x[1,...,i],y[1,...,j])|c[n,m]=|LCS(X,Y)|

從而可以得到 c[i,j] 的遞歸表達式:
c[i,j]={c[i1,j1]+1,max{c[i,j1],c[i1,j]},if x[i]=y[j]otherwise

從而引出動態規劃的第一個重要性質——最優子結構:如果一個問題的最優解包含其子問題的最優解,那麼我們稱此問題具有最優子結構的性質。上面遞歸表達式中,c[i,j] 的最優解必然包含 c[i,j1]c[i1,j] 的最優解。
基於以上表達式,我們可以構建求解 c[i,j] 的遞歸算法,其僞代碼表示爲:
LCS(X,Y,i,j)if(X[i]=Y[j]):thenc[i,j]=LCS(X,Y,i1,j1)+1elsec[i,j]=max{LCS[X,Y,i1,j],LCS[X,Y,i,j1]}returnc[i,j]

求解的最差情況是X[i]Y[j],(ij)
根據上面的遞歸表達式,我們以n=7,m=6 爲例,畫出求解問題的迭代樹。(不知道用markdown如何生成這種圖片,就手畫了。。。)
LCS迭代樹
可以發現,會有很多遞歸求解是重複的,這就引出了動態規劃的第二個重要性質——重疊子問題:如果遞歸算法反覆求解相同的子問題,則稱該問題具有重疊子問題。LCS的問題包含了 mn 個獨立子問題。爲了減少重複計算,通常會將子問題的結果存入表中,每次查表獲取子問題的解,或許因爲查表,所以動態規劃(programming),這個表也被成爲備忘表。此時,遞歸僞代碼變爲:
ifc[i,j]=nil:LCS[X,Y,i,j]else:c[i,j]

此時求解LCS的時間複雜度變爲Θ(mn) ,空間複雜度爲Θ(mn)
以上即爲帶備忘的自頂向下求解LCS的方法,通過增加空間複雜度,大大降低了時間複雜度。

2.3 自底向上動態規劃

自頂向下的方法中,每次會對自身進行迭代,獲取當前需要的子問題,相當於一個從大到小的轉變。在某些情況下,自頂向下對方法並未考慮所有的子問題(比如某些子問題併爲必須求解的),而且,頻繁地遞歸調用會有一定的開銷,因此考慮自底向上,求解全部的子問題的最優解,進而求解最終的最優解,簡單的僞代碼如下:

LCS_LENGTH(X,Y)letc[1...n,1...m]beanewtablefori=1ton:forj=1tom:ifX[i]=Y[j]:c[i,j]=c[i1,j1]+1elifc[i1,j]c[i,j1]:c[i,j]=c[i1,j]else:c[i,j]=c[i,j1]

通過該代碼,即可求出LCS的長度,即最優解的值。爲了求出LCS的具體元素,可以額外使用一個數組儲存每次尋找的路徑,從而獲取最優解。

3. 動態規劃基本策略

綜上,可以總結一下動態規劃的基本策略:
1. 刻畫一個最優解的結構特徵
2. 遞歸地定義最優解的值
3. 計算最優解的值,通常採用自底向上的方法
4. 利用計算出的信息構造一個最優解

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