DP系列-leetcode 673. Number of Longest Increasing Subsequence

题目描述:

Given an unsorted array of integers, find the number of longest increasing subsequence.

Example 1:

Input: [1,3,5,4,7]
Output: 2
Explanation: The two longest increasing subsequence are [1, 3, 4, 7] and [1, 3, 5, 7].

Example 2:

Input: [2,2,2,2,2]
Output: 5
Explanation: The length of longest continuous increasing subsequence is 1, and there are 5 subsequences' length is 1, so output 5.
Note: Length of the given array will be not exceed 2000 and the answer is guaranteed to be fit in 32-bit signed int.

思路:

我们已经做过最长递增子序列了https://blog.csdn.net/orangefly0214/article/details/89343811

本题就是在最长递增子序列的基础上增加了条件,让我们计算最长的子序列的个数。

我们以dp[i]表示nums[i]为结尾的的递增序列的长度,

       以cnt[i]表示以nums[i]为结尾的递增序列的个数。初始值 设为1,因为只要有数,那最长递增子序列及其个数都至少为1.

对递增序列的判断和300题一样,逐个各边nums中的每个元素,每遍历到一个元素i,都将它前面的每个元素与它作比较:

若nums[i]<nums[j],则dp数组和cnt数组都不做任何改变,因为这种情况下并不会构成递增序列;

若nums[i]>nums[j],此时我们需要判断dp[i]与dp[j]的关系:

          若dp[i]<dp[j]+1,此时说明我们在原来长度的基础上找到一条更长的序列,

                                   此时dp[i]=dp[j+1],此时i所对应的最长递增子序列的个数和j对应的是一样的,cnt[i]=cnt[j]。(因为新增的这个序列是在原序列的基础上增加的。)

          若dp[i]=dp[j]+1,则说明以dp[j]+1为长度的最长递增子序列已经被上一个j更新过了,此时又相等,说明当前这个j和上一个j都能构成长度为dp[j]+1的最长递增子序列。

比如:

实现:

import java.util.Arrays;
class Solution {
    public int findNumberOfLIS(int[] nums) {
        int n=nums.length;
        int max_len=1;
        int[] dp=new int[n];
        int[] cnt=new int[n];
        Arrays.fill(dp,1);
        Arrays.fill(cnt,1);
        for(int i=1;i<n;i++){
            for(int j=0;j<i;j++){
                if(nums[j]<nums[i]&&dp[j]+1>dp[i]){
                    dp[i]=dp[j]+1;
                    cnt[i]=cnt[j];
                }else if(nums[j]<nums[i]&&dp[j]+1==dp[i]){
                    //此时说明dp[i]已经被上一个j更新过了,也意味着出现了一个新的能使当前长度达到dp[i] 的值
                    cnt[i]+=cnt[j];
                }
            }
            max_len=Math.max(dp[i],max_len);
        }
        int ret=0;
        for(int i=0;i<n;i++){
            if(dp[i]==max_len){
                ret+=cnt[i];
            }
        }
        return ret; 
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值