题意:给个序列,求最长上升子序列
1、返回子序列长度
2、返回该序列(字典序最小)
题解:
dp[i] 表示以 nums[i] 结尾的「上升子序列」的长度
len[i] 表示长度为 i+1 的所有上升子序列结尾的最小值
int lengthOfLIS(vector<int>& arr) {
int n = arr.size();
vector<int> len(n+1, -1), dp(n);
int maxn = 1;
len[maxn] = arr[0];
dp[0] = maxn;
for (int i = 1; i < n; ++i) {
if (arr[i] > len[maxn]) {
len[++maxn] = arr[i];
dp[i] = maxn;
}
else {
int left = 1, right = maxn, pos = 0;
while (left <= right) {
int mid = left + right >> 1;
if (len[mid] < arr[i]) {
pos = mid;
left = mid + 1;
}
else right = mid - 1;
}
len[pos+1] = arr[i];
dp[i] = pos+1;
}
}
vector<int> ans(maxn);
for (int i = n-1; i >= 0; --i) {
if (dp[i] == maxn) {
ans[--maxn] = arr[i];
}
}
for (auto &x : ans)
cout << x << " ";
return ans.size();
}
库函数二分
int lengthOfLIS(vector<int>& nums) {
vector<int> dp;
dp.push_back(nums[0]);
for (int i = 1; i < nums.size(); ++i) {
if (nums[i] > dp.back())
dp.push_back(nums[i]);
else {
int pos = lower_bound(dp.begin(), dp.end(), nums[i])-dp.begin();
dp[pos] = nums[i];
}
}
int ret = dp.size();
return ret;
}