1. 程式人生 > >動態規劃求最長遞增子序列的長度

動態規劃求最長遞增子序列的長度

main cpp 動態規劃 using string sub 給定 數組最長遞增子序列 ios

問題

給定一個長度為N的數組,找出一個最長的單調自增子序列(不一定連續,但是順序不能亂)。例如:給定一個長度為6的數組A{5, 6, 7, 1, 2, 8},則其最長的單調遞增子序列為{5,6,7,8},長度為4.

設長度為N的數組為{a0,a1, a2, ...an-1),則假定以aj結尾的數組序列的最長遞增子序列長度為L(j),

則  L(j)={ max(L(i))+1, i<j且a[i]<a[j] }。

也就是說,我們需要遍歷在j之前的所有位置i(從0到j-1),找出滿足條件a[i]<a[j]的L(i),求出max(L(i))+1即為L(j)的值。最後,我們遍歷所有的L(j)(從0到N-1),找出最大值即為最大遞增子序列。時間復雜度為O(N^2)。

例如給定的數組為{5,6,7,1,2,8},則L(0)=1, L(1)=2, L(2)=3, L(3)=1, L(4)=2, L(5)=4。所以該數組最長遞增子序列長度為4,序列為{5,6,7,8}。算法代碼如下:

#include <iostream>
using namespace std;
#define len(a) (sizeof(a) / sizeof(a[0])) //數組長度
int lis(int arr[], int len)
{
    int longest[len];
    for (int i=0; i<len; i++)
        longest[i] = 1;

    for (int j=1; j<len; j++) {
        for (int i=0; i<j; i++) {
            if (arr[j]>arr[i] && longest[j]<longest[i]+1){ //註意longest[j]<longest[i]+1這個條件,不能省略。
                longest[j] = longest[i] + 1; //計算以arr[j]結尾的序列的最長遞增子序列長度
            }
        }
    }

    int max = 0;
    for (int j=0; j<len; j++) {
        cout << "longest[" << j << "]=" << longest[j] << endl;
        if (longest[j] > max) max = longest[j];  //從longest[j]中找出最大值
    }
    return max;
}

int main()
{
    int arr[] = {1, 4, 5, 6, 2, 3, 8}; //測試數組
    int ret = lis(arr, len(arr));
    cout << "max increment substring len=" << ret << endl;
    return 0;
}

  運行結果:

技術分享圖片

動態規劃求最長遞增子序列的長度