用LCS解决LIS问题
最长上升子序列有它的套路,不过用LCS算法是可以解决的:
假设原序列为
A
第一步:现在对原序列进行排序得到排序后的序列
第二步:考虑原序列
A
可能有重复元素,对序列
第三步:对
A
和
好,这个算法在LeetCode是Memory Limit
代码
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
vector<int>copied_nums(nums.begin(),nums.end());
//排序
sort(copied_nums.begin(),copied_nums.end());
//去重
copied_nums.erase(
unique(copied_nums.begin(),copied_nums.end()),
copied_nums.end());
int m=nums.size();
int n=copied_nums.size();
vector<vector<int>>dp(m+1,vector<int>(n+1));
//计算LCS
for(int i=0;i<m;++i)
{
for(int j=0;j<n;++j)
{
if(nums[i]==copied_nums[j])
{
dp[i+1][j+1]=dp[i][j]+1;
}
else
{
dp[i+1][j+1]=max(dp[i+1][j],dp[i][j+1]);
}
}
}
return dp[m][n];
}
};
LIS动态规划
LIS还是有它的套路,比如动态规划方程如下:
注意这里的
dp(i)
是一个局部最优,表示当LIS以
ai
结尾时的最优,因此我们首先要从
0 i−1
找一各满足
aj<ai
条件的局部最优,再在后面补上
ai
即是当前局部最优。
有了动归方程,再根据动归方程算出的局部最优解求全局最优就很EZ了。
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int m=nums.size();
if(0==m||1==m)
return m;
vector<int>L(m);
L[0]=1;
int curMax;
int res=0;
for(int i=1;i<m;++i)
{
curMax=0;
for(int j=0;j<i;++j)
{
if(nums[i]>nums[j])
{
curMax=max(curMax,L[j]);
}
}
L[i]=curMax+1;//局部最优
res=max(L[i],res);//全局最优
}
return res;
}
};