题目:
给定一个长度为N的数组,找出一个最长的单调自增子序列(不一定连续,但是顺序不能乱)
例如:给定一个长度为8的数组A{1,3,5,2,4,6,7,8},则其最长的单调递增子序列为{1,2,4,6,7,8},长度为6.
输入描述:
第一行包含一个整数T,代表测试数据组数。
对于每组测试数据:
N-数组的长度
a1 a2 ... an (需要计算的数组)
保证:
1<=N<=3000,0<=ai<=MAX_INT.
输出描述:
对于每组数据,输出一个整数序列,代表最长递增子序列。
若有多组最长上升子序列,输出第一组。
保证:1<=T<=20,1<=N<=3000,0<=ai<=MAX_INT.
输入例子:
2 7 89 256 78 1 46 78 8 5 6 4 8 2 17
输出例子:
1 46 78 6 8 17
思路:
上一道题是输出最长递增子序列的长度,而这一道是要求输出序列。只要再维护一个pos数组,保存第i个数的上一个序列内数的位置即可。例如序列5 1 6 50 9 12,第4
个数9的上一个序列数为6, 下标为3,那么pos[4] = 3
代码:
1 #include <iostream> 2 #include <algorithm> 3 #include <vector> 4 using namespace std; 5 6 vector<int> getMaxSub(vector<int> v) 7 { 8 int size = v.size(); 9 vector<int> len(size,1); 10 vector<int> pos(size);//记录位置 11 //res[i]代表以第i个元素结尾的长度 12 for (int i = 0; i < size; ++i) 13 { 14 for (int j = 0; j < i; ++j) 15 { 16 if (v[j] < v[i] && len[i] < len[j] + 1) 17 { 18 len[i] = len[j] + 1; 19 pos[i] = j; 20 } 21 } 22 } 23 24 int max = -1; 25 int lastPos = -1; 26 for (int i = 0; i < len.size(); ++i) 27 { 28 if (max < len[i]) 29 { 30 max = len[i]; 31 lastPos = i; 32 } 33 } 34 35 vector<int> res; 36 for (int i = 0; i < max; ++i) 37 { 38 res.push_back(v[lastPos]); 39 lastPos = pos[lastPos]; 40 } 41 reverse(res.begin(), res.end()); 42 43 return res; 44 } 45 46 int main() 47 { 48 int T; 49 cin >> T; 50 vector<int> v; 51 while (T--) 52 { 53 int size; 54 cin >> size; 55 int temp; 56 for (int i = 0; i < size; ++i) 57 { 58 cin >> temp; 59 v.push_back(temp); 60 } 61 auto ans = getMaxSub(v); 62 63 for (int i = 0; i < ans.size() - 1;++i) 64 { 65 cout << ans[i] << ' '; 66 } 67 cout << ans[ans.size() - 1] << endl; 68 v.clear(); 69 } 70 return 0; 71 }