leetcode-673-最长递增子序列的个数
[博客链接]
[题目链接]
[github地址]
[题目描述]
给定一个未排序的整数数组,找到最长递增子序列的个数。
示例 1:
输入: [1,3,5,4,7]
输出: 2
解释: 有两个最长递增子序列,分别是 [1, 3, 4, 7] 和[1, 3, 5, 7]。
示例 2:
输入: [2,2,2,2,2]
输出: 5
解释: 最长递增子序列的长度是1,并且存在5个子序列的长度为1,因此输出5。
思路一:序列dp
- 常规序列dp的题
- 因为求的是子序列的数量
- 我们需要定义两个dp数组
- dp[i] 表示以第i个字符为结尾的最长递增子序列的长度
- cnt[i] 表示以第i字符为结尾的最长递增子序列的数量
- dp转移过程分析
- dp[0] = 1;
- 当nums[i] > nums[j] 的时候dp[i] = dp[j]+1
- 反之dp[i] = 1;
- cnt转移过程分析
- 与上述过程分析基本一致
- cnt[0] =1 ;
- 当nums[i] > nums[j] 的时候分两种情况判断
- 判断当前元素是否可以拼在前面元素后面组成新的递增子序列
- 如果可以也就是说**dp[i] == dp[j+1] **那么cnt[i] += cnt[j];
- dp[i]< dp[j+1]则重置 cnt[i] = cnt[j];
- 最后返回dp最大的对应的cnt数值即可
public int findNumberOfLIS(int[] nums) {
int[] dp = new int[nums.length];
int[] cnt = new int[nums.length];
dp[0] = 1;
cnt[0] = 1;
int max = 0;
for(int i = 0;i < nums.length; i++){
dp[i] = cnt[i] = 1;
for(int j = 0; j < i;j++){
if(nums[i]> nums[j]){
if(dp[i]<dp[j]+1){
cnt[i]=cnt[j];
dp[i] = dp[j]+1;
}else if(dp[i]== dp[j]+1){
cnt[i]+=cnt[j];
}
}
}
max = Math.max(dp[i],max);
}
int res = 0;
for(int i = 0; i < nums.length; i++){
if(max == dp[i]){
res +=cnt[i];
}
}
return res;
}
- 时间复杂度:O()
- 空间复杂度:O()