【LeetCode_673】最长递增子序列的个数
题目描述:

解释:这道题是力扣第三百题——最长上升子序列的进阶,与之不同的是300题要求的是最长上升子序列的长度,而这题需要我们求最长上升子序列的个数。我们可以借助动态规划来解决这道题。
首先定义一个一维数组dp[i],表示考虑前i个数字的最长上升子序列的长度。然后,题目由于要求最长的上升子序列的数目,所以我们需要维护另一个数组count[i],表示前i个数字长度为dp[i]的子序列的个数。
class Solution {
public:
int findNumberOfLIS(vector<int>& nums) {
int n=nums.size();
vector<int> dp(n+1,1);
vector<int> count(n+1,1);
for(int i=1;i<=n;i++){
for(int j=1;j<=i;j++){
if(nums[j-1]<nums[i-1]){
if(dp[j]>1+dp[i]){ //[0:i]有1个最长子序列
dp[i]=1+dp[j];
count[i]=count[j];
}
else if(dp[i]==dp[j]+1){ //[0:i]有多个最长子序列
count[i]+=count[j];
}
}
}
}
int longest=0;
int ret=0;
for(int i=1;i<=n;i++){
longest=max(longest,dp[i]);
}
for(int i=1;i<=n;i++){
if(longest==dp[i]){
ret+=count[i];
}
}
return ret;
}
};
我们重点来看这一段:
if(nums[j-1]<nums[i-1]){
if(dp[j]>dp[i]+1){ //[0:i]有1个最长子序列
dp[i]=1+dp[j];
count[i]=count[j];
}
else if(dp[i]==dp[j]+1){ //[0:i]有多个最长子序列
count[i]+=count[j];
}
}
在nums[j-1]<nums[i-1]的情况下,如果dp[j]>=dp[i],也就是说在[0:i-1]内找到了一个更长的子串,此时count[i]自然就要等于count[j]
如果在[0, i-1]的范围内,找到了j,使得dp[j] + 1 == dp[i],说明找到了两个相同长度的递增子序列。那么以i为结尾的子串的最长递增子序列的个数 就应该加上以j为结尾的子串的最长递增子序列的个数,即:count[i] += count[j];
- 时间复杂度:O(N2)。N为nums的长度。

浙公网安备 33010602011771号