题目链接:https://leetcode-cn.com/problems/longest-increasing-subsequence/
题意:
给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。
子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。
方法一:动态规划 ,时间复杂度O(n^2),空间复杂度O(n)
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int dp[2501]={0};//dp数组
int len = nums.size();//记录元素个数
int maxL = 1;//最大长度至少为1
dp[0] = 1;
for(int i=1;i<len;i++)//遍历数组中的每个元素
{
dp[i] = 1;
for(int j=0;j<i;j++)//遍历nums[i]之前的每一个元素
{
if(nums[i]>nums[j])//如果数组中的数[i]要比前面几个数大,寻找到最大的dp[j]在它的基础上加1,更新到dp[i]中
dp[i] = max(dp[i],dp[j]+1);
}
maxL = max(maxL,dp[i]);//每一次dp[i]更新完,就更新一下最大值
}
return maxL;
}
};
方法二:动态规划+二分查找,时间复杂度O(nlogn),空间复杂度O(n)
构造dp数组,通过lower_bound达到logn的效率,替换掉第一个大于等于nums[i]的元素,每次都这么替换,最后的dp数组中,会找到最优的子序列长度
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int len = nums.size();//记录元素个数
vector<int> dp(len,1e9+1);//构造dp数组
for(int i=0;i<len;i++)//遍历nums每一个元素
{
int index = lower_bound(dp.begin(),dp.end(),nums[i])-dp.begin();//记录下第一个大于等于nums[i]的元素的坐标
dp[index] = nums[i];//替换dp数组中的这个元素
}
return lower_bound(dp.begin(),dp.end(),1e9+1)-dp.begin();//返回最大的长度
}
};