1. 程式人生 > 實用技巧 >最長遞增子序列問題

最長遞增子序列問題

問題描述:

子序列定義:選取某一序列中的某些元素,並按原序組成的序列即為原序列的子序列

遞增子序列:其中元素嚴格增大的子序列

輸入:一個數字序列 a[1..n]

輸出:具有最大長度的遞增子序列

演算法描述:

對於此演算法,可以將該序列進行排序構成序列b[1..n],而後利用LCS演算法進行求解即可。

1.分析優化子結構。

如果原問題的最長遞增子序列包含某個元素ak,那麼,該最長遞增子序列一定包含數字序列a[1...k-1]的最長遞增子序列。這裡沒有使用“就是”而是使用“包含”,是因為數字序列a[1...k-1]的最長子序列可能不唯一。

證明,可以使用反證法進行簡單的證明。

2.分析子問題重疊性。

對於原問題而言,其最長遞增子序列的選取需要解決問題:a[1...k] , (1≤k≤n),的最長遞增子序列。這其中明顯就會具有較大的重疊性,比如ak,ak+1的計算就需要都處理a[1...k-1]的問題。

3.遞迴地定義最優解的代價

定義:dp[i]表示,數字序列a[1...i]的以第i 個元素結尾的最長遞增子序列的長度。

dp[ i ] = max { dp[j] | 0 < j < i; aj < ai } + 1;

dp[ 1 ] = 1;

4.自底向上地計算優化解的代價儲存之,並獲取構造最優解的資訊

根據遞迴式可以確定其儲存子問題的最優解的代價的資料結構為一維陣列。繼而確定其資料結構的填充順序為:直接按照下標順序填充即可。

故而可以設計演算法為:

LIS演算法
輸入:陣列a[1..n] 
輸出:   a的最長遞增子序列長度
FOR  i =  TO  n 
       dp[i] ← 0; 
       FOR  j  =1  TO  i – 1 
              IF  a[j] < a[i] AND dp[j] > dp[i] 
              THEN  dp[i] ← dp[j]; 
                        dp[i] ← dp[i] + 1; 
RETURN dp[n]

  演算法複雜性分析:

時間複雜性:計算代價的時間:O(n^2),顯然。

空間複雜性:O(n)。