最长上升子序列
给定一个无序的正数数组,找到其中最长上升子序列的长度
示例
输入:[10,9,2,5,3,7,101,18]
输出:4
解释:最长的上升子序列是 [2,3,7,101],它的长度是 4
思路
动态规划,\(dp[i]\)表示以\(nums[i]\)结尾的最长上升子序列长度
\[nums[i]>nums[j] ==> dp[i]=max(dp[j])+1
\]
代码
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
//dp[i]表示以数字i结尾的最长上升子序列长度
vector<int> dp(nums.size(),0);
if(nums.empty()) return 0;
for(int i=0;i<nums.size();i++)
{
dp[i]=1;
for(int j=0;j<i;j++)
{
if(nums[i]>nums[j])
dp[i]=max(dp[i],dp[j]+1);
}
}
return *max_element(dp.begin(),dp.end());
}
};
给定一个未排序的整数数组,找到最长递增子序列的个数
示例
输入:[1,3,5,4,7]
输出:2
解释:有两个最长递增子序列,分别是 [1, 3, 4, 7] 和[1, 3, 5, 7]
思路
动态规划,相比于第一题,新增一个\(counter[i]\)表示以\(nums[i]\)结尾的最长递增子序列的组合数量
-
总体需满足\(nums[i]>nums[j]\)
-
若\(dp[j]+1>dp[i]\),说明第一次找到以\(nums[i]\)为结尾的最长递增子序列,长度为\(dp[j]+1\),进而可以推出\(counter[i]==counter[j]\)
-
若\(dp[j]+1==dp[i]\),说明这个长度已经找到过一次,\(counter[i]+=counter[j]\)
代码
class Solution
{
public:
int findNumberOfLIS(vector<int> &nums)
{
vector<int> dp(nums.size(), 0);
vector<int> counter(nums.size(), 1);
if (nums.empty()) return 0;
for (int i = 0; i < nums.size(); i++)
{
dp[i] = 1;
for (int j = 0; j < i; j++)
{
if (nums[i] > nums[j])
{
if (dp[j] + 1 > dp[i])
{
dp[i] = max(dp[i], dp[j] + 1);
counter[i] = counter[j];
} else if (dp[j] + 1 == dp[i])
counter[i] += counter[j];
}
}
}
int res = 0;
int length = *max_element(dp.begin(), dp.end());
for (int i = 0; i < dp.size(); ++i)
{
if (dp[i] == length)
res += counter[i];
}
return res;
}
};

浙公网安备 33010602011771号