在原题的基础上,维护一个pos数组,当更新dp时,保存当前节点 i 的前一个结点 j 的下标(因为dp[i]是需要dp[j]来推出的)。
另外用max和lastPos分别保存最长递增子序列的最后一个(即最大)元素和下标,然后通过遍历pos数组,从后向前地把目标数组构造完成。
#include<bits/stdc++.h>
#include<sstream>
#include<string>
using namespace std;
class Solution {
public:
vector<int> lengthOfLIS(vector<int>& nums) {
int n = nums.size();
int ans = 0;
if(n <= 1) return {};
vector<int> dp(n, 1);
vector<int> pos(n); //记录位置
for(int i = 0; i < n; i++) {
for(int j = 0; j < i; j++) {
if(nums[i] > nums[j]) {
dp[i] = max(dp[i], dp[j] + 1);
pos[i] = j; //记录最长递增路径中当前节点的前置节点
}
if(dp[i] > ans) ans = max(ans, dp[i]);
}
}
int max = -1; //最长递增序列的长度
int lastPos = -1; //找到最长递增序列最后一个元素的位置
for(int i = 0; i < n; i++) {
if(max < dp[i]) {
max = dp[i];
lastPos = i;
}
}
//最长递增序列的路径,从后先前寻找
vector<int> res;
for(int i = 0; i < max; ++i) {
res.push_back(nums[lastPos]);
//更新当前节点的前置接点
lastPos = pos[lastPos];
}
reverse(res.begin(), res.end());
return res;
}
};
int main() {
Solution s;
vector<int> nums{10,9,2,5,3,7,101,18};
vector<int> path = s.lengthOfLIS(nums);
for(int num:path) {
cout<<num<<" ";
}
return 0;
}