最長遞增子序列
給定數組arr,設長度為n,輸出arr的最長遞增子序列。(如果有多個答案,請輸出其中字典序最小的)
輸入描述
輸出兩行,第一行包括一個正整數n(n<=100000),代表數組長度。第二行包括n個整數,代表數組arr \left(1 \leq arr_i \leq 1e9 \right)(1≤arri≤1e9)。
輸出描述
輸出一行。代表你求出的最長的遞增子序列。
示例1
輸入
9 2 1 5 3 6 4 8 9 7
輸出
1 3 4 8 9
示例2
輸入
5
1 2 8 6 4
輸出
1 2 4
說明:其最長遞增子序列有3個,(1,2,8)、(1,2,6)、(1,2,4)其中第三個字典序最小,故答案為(1,2,4)
#include <iostream> #include <vector> using namespace std;
//判斷兩個數組那個字典序排列在前 bool dictOrder(vector<int> cur, vector<int> competitor){ for(int i = 0; i < competitor.size(); i++){ if(cur[i] <= competitor[i]){ continue; } else{ return false; } } return true; }
//動態規划,記錄i每向前移一位時,搜索以input[i]結尾的最長遞增子序列,並將這個子序列存儲在“store”數組中。 vector<int> fun(vector<int>& input){ vector<vector<int>> store(input.size()); store[0] = {input[0]}; for(int i = 1; i < input.size(); i++){ int longest = 0; for(int j = 0; j < i; j++){ if(*store[j].rbegin() < input[i]){ if(store[j].size() + 1 > longest){ store[i] = store[j]; store[i].emplace_back(input[i]); longest = store[j].size(); } else if(store[j].size() + 1 == longest){ if(dictOrder(store[i], store[j]) == false){ store[i] = store[j]; store[i].emplace_back(input[i]); longest = store[j].size(); } } } } if(store[i].size() == 0){ store[i].emplace_back(input[i]); } }
//找出所有以input[i]結尾的遞增子序列中最長的 vector<int> ans; for(auto &vec : store){ if(ans.size() < vec.size()){ ans = vec; } else if(ans.size() == vec.size() && vec.size() && ans.size()){ if(dictOrder(ans, vec) == false){ ans = vec; } } } return ans; } int main() { int n; cin >> n; vector<int> input(n); for(int i = 0; i < n; i++){ cin >> input[i]; } vector<int> ans = fun(input); for(int num : ans){ cout << num << ' '; } return 0; }
