1.动态规划
数组长度为n,dp[n]初始值全为1,对dp[i]依次计算0--i-1,将i放到其后的子序列长度,
即j<i,dp[i]=max(dp[i],dp[j]+1);
最后,遍历dp数组,求最大值
代码如下:
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
//最长子序列不需要连续
int len=nums.size();
if(len==0)
return 0;
vector<int> dp(len,1);//首先由len个子序列,每个序列的长度都是1
dp[0]=1;
for(int i=1;i<len;i++)
for(int j=0;j<i;j++)
if(nums[i]>nums[j])//当遇到比自己小的,就考虑就自己放在其后上升子序列的长度
dp[i]=max(dp[i],dp[j]+1);
int m=dp[0];
for(int i=1;i<len;i++)//最后,遍历整个dp,求出最大值
m=max(dp[i],m);
return m;
}
};
时间复杂度O(n*n),空间复杂度O(n)
2.动态规划+二分查找
新建一个数组res存放上升子序列
对原序列进行遍历,将每个元素二分插入res中
如果res中的元素都比它小,则直接插到最后
否则,用它覆盖掉比它大的元素中最小的那个。
代码如下:
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
//最长子序列不需要连续
int len=nums.size();
if(len==0)
return 0;
vector<int> res(len,0);
int count=0;//记录到当前元素i最大上升子序列的长度
res[count++]=nums[0];
for(int i=1;i<len;i++)
{
if(nums[i]>res[count-1])//nums[i]比res中所有元素都大
res[count++]=nums[i];
else
{
int left=0,right=count-1;
while(left<=right)//二分法这样写可以保证严格上升
{
int mid=left+(right-left)/2;
if(res[mid]<nums[i])
left=mid+1;
else
right=mid-1;
}
res[left]=nums[i];
}
}
return count;
}
};