北京大學郭煒-最長上升子序列 動態規劃講解

Vichien_Chen發表於2020-10-14

北京大學郭煒-最長上升子序列 動態規劃講解

問題原型:

在這裡插入圖片描述
解題思路:
找子問題,題目要求我們求1~n的最長上升子序列的長度,那我們想一想:1-2個元素的最長上升子序列的長度是多少,第1個元素的最長上升子序列又是多少?
假設我們輸入一個序列:

9
2 7 1 5 6 4 3 8 9

顯然
第1個元素的最長上升子序列的長度為1
1-2個元素的最長上升子序列為(2 7),長度為2
1-3個元素的最長上升子序列為(2 7)(2 1),長度為2
1-4個元素的最長上升子序列有(2 7)(2 1)(2 5)(1 5),長度也為2
由此可見,我們是可以通過遍歷0~i-1個元素的最長上升子序列來得到i的最長上升子序列的。

我們建立一個和輸入序列一樣長的陣列maxLen,來記錄每一個元素從0~該元素位置的最長上升子序列的長度。maxLen中每一個元素的初值為1,因為倘若序列中元素i前面的數字都比i大,那麼元素i對應位置的最長上升子序列長度就是自己一單位的長度,即為1。

在這裡插入圖片描述
具體寫法我們程式碼裡面說:

#include "iostream"
#include <vector>
#include <algorithm>
using namespace std;
int main(){
    int n,elem;
    vector<int> a,maxLen;
    cin>>n;
    for (int i=0;i<n;i++){
        cin>>elem;
        a.push_back(elem);
        // 設定每個元素預設最長上升子序列為1
        maxLen.push_back(1);
        //maxLen記錄的是第0個元素到第i個元素的最長上升子序列的長度
    }

    //第一層for迴圈遍歷輸入的每一個元素,找出該元素的最長上升子序列的長度
    for (int i=1;i<n;i++){
        //第二層for迴圈遍歷該元素前所有的元素
        for (int j=0;j<i;j++){
            //如果元素a[i]大於元素a[j],說明序列上升了
            if (a[i]>a[j]){
                maxLen[i] = max(maxLen[i],maxLen[j]+1);
            }
        }
    }
    sort(maxLen.begin(),maxLen.end(),greater<int>());
    cout<<maxLen[0];
}

相關文章