给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。并输出该子序列,如果有多个子序列,则输出字典序最小的一个。
子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。
输入:nums = [10,9,2,5,3,7,101,18] 输出:4 解释:最长递增子序列是[2,5,7,101], [2,3,7,101],[2,3,7,18]...长度为 4 输出[2,3,7,18]
解法:贪心+二分
参考Leetcode300
这里需要增加一个数组maxLen,maxLen[i]表示以nums[i]结尾的最长子序列的长度。vec[i]则表示长度为i的最长上升序列末尾元素的最小值。
在恢复子序列时,从后往前开始遍历maxLen,找到最右一个满足长度条件的对应nums数组中的元素,加入结果集。
vector<int> LIS(vector<int>& nums){
int n=nums.size();
vector<int> vec;
vec.push_back(nums[0]);
vector<int> maxLen;
maxLen.push_back(1);
for(int i=1; i<n; ++i){
if(nums[i] > vec.back()){
vec.push_back(nums[i]);
maxLen.push_back(vec.size());
}
else{
int len=maxLen[i-1];
int left=0, right=len-1;
while(left <= right){
int mid=(left+right)>>1;
if(vec[mid] < nums[i]){
left=mid+1;
}else{
right=mid-1;
}
}
vec[left]=nums[i];
maxLen.push_back(left+1);
}
}
int len=vec.size();
vector<int> ans(len);
for(int i=n-1; i>=0; --i){
if(maxLen[i]==len){
ans[--len]=nums[i];
}
}
return ans;
}