1. 程式人生 > >最長遞增子序列(longest increasing subsequence) 問題詳解

最長遞增子序列(longest increasing subsequence) 問題詳解

最長遞增子序列的定義:
按照序列元素的下標號,抽取一部分元素組成子序列,子序列中的元素之間為遞增的關係(下標可以不連續)。其中長度最長的遞增子序列就是最長遞增子序列。

方法思想:
為了求出該陣列的最長遞增子序列,就需要先求出在以陣列中每個元素為結尾的情況下,最長的遞增子序列是什麼樣的。因此首先要申請一塊二維陣列空間,存放以各個元素為結尾情況下的最長遞增子序列。

首先顯然可知,以0號元素為結尾的子序列只有0號元素自己。然後計算以1號元素為結尾的子序列,以此類推。

當計算n號的元素對應的子序列時,可以用n號元素與n-1號子序列的末尾元素比較,若n號元素大,則n號元素 暫時 求出的子序列就是n-1號元素對應子序列再加上n號元素。然後,將n號元素與n-2號元素對應子序列做同樣對比,依次計算下去,選擇一個可以使n號元素的子序列最長的情況。

按照上述方法,依次計算每個元素對應的結果之後的子序列,選擇一個長度最長的序列即為整個陣列的最長遞增子序列。
按照同樣的道理可以求出最長遞減子序列。

舉例說明上述思想:
對於序列A{35, 36, 39, 3, 15, 27, 6, 42}當處理到最後一個元素42時,以35, 36, 39, 3, 15, 27, 6為最末元素的最長遞增序列分別為:
35
35,36
35,36,39
3
3,15
3,15,27
3,6
下面來計算42元素對應的子序列,首先將42與上述子序列末尾元素比較大小,小於42時,將42加入上述序列末尾,比較各個序列的長度,選擇長度最長的,如下:
35,42
35,36,42
35,36,39,42,
3,42
3,15,42
3,15,27,42
3,6,42
這其中最長的遞增序列為(35,36,39,42)和(3,15,27,42),所以序列A的最長遞增子序列的長度為4,在A中長度為4的遞增子序列不止一個。
則整個陣列的最長遞增子序列長度為4。

程式碼編寫:

#include <iostream>
#include <vector>
using namespace std;

void lis(int a[], vector<int> *vt, int len){
    for(int i = 0; i < len; i++){
        vt[i].push_back(a[i]);
        for(int j = i - 1; j >= 0; j--){
            if(a[i] > vt[j].back() && vt[j].size() > (vt[i].size()-1
)){ //選擇長度最長的 vt[i] = vt[j]; vt[i].push_back(a[i]); } } } } //求序列 35, 36, 39, 3, 15, 27, 6, 42 的最長遞增子序列 int main(){ int len = 8; int a[] = {35, 36, 39, 3, 15, 27, 6, 42}; vector<int> *vt = new vector<int>[len]; lis(a, vt, len); for(int i = 0; i < len; i++){ for(int j = 0; j < vt[i].size(); j++){ cout<<vt[i][j]<<' '; } cout<<endl; } return 0; }