给定一个无序的整数数组,找到其中最长上升子序列的长度。
示例:
输入: [10,9,2,5,3,7,101,18]
输出: 4
解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4。
说明:
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-increasing-subsequence
算法一:用f[i]表示以下标i结束的最长上升子序列,每次有i个决策,需要在i之前去寻找最长的且比nums[i]小的f[j] ,时间复杂度是n^2
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
//base case
if(nums.empty())return 0;
vector<int> f(nums.size());
f[0]=1;
int ans=f[0];
for(int i=1;i<nums.size();++i){
for(int j=0;j<i;++j){
if(nums[i]>nums[j])
f[i]=max(f[j]+1,f[i]);
else f[i]=max(f[i],1);
}
ans=max(ans,f[i]);
}
return ans;
}
};
算法二:nlogn 这里优化了寻找比当前值小的最长长度,用二分来找,因为我们可以发现若以长度为下标,那么存储的若是nums的值,是具有单调性的,反证法,若后面的小于前面的,那末前面的长度一定比后面的长,出现矛盾,假设错误,找到单调性我们就可以利用二分去寻找比当前值小的最长长度,l=0,r=len;
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
vector<int> sum(nums.size()+10);
int len=0;
sum[0]=-2e9;
for(int i=0;i<nums.size();++i){
int l=0,r=len;
while(l<r){
int mid=l+r+1>>1;
if(sum[mid]<nums[i])l=mid;
else r=mid-1;
}
len=max(len,r+1);
sum[r+1]=nums[i];
}
return len;
}
};