673.最长递增子序列的个数

给定一个未排序的整数数组,找到最长递增子序列的个数。

题目链接:673. 最长递增子序列的个数 - 力扣(LeetCode) (leetcode-cn.com)

动态规划

思路

这题对于dp数组的处理与leetcode300题相同。

  • 首先确定动态数组 dp[i] 的含义:表示到数组第i位置为止最长递增子序列的长度

  • 确定动态转移方程:

    • 遍历已知数组从位置0到位置i-1,若 nums[i] > nums[j] 说明当前i位置的数可以和0~j已经组成递增子序列的序列组成更长的子序列。
    • dp[i] = max( dp[i] , dp[j]+1 )
  • 但是此题最后问的是最长递增子序列的个数,于是我们增加一个 count 数组,count[i] 表示以nums[i] 为末尾的最长子序列的个数。怎么更新 count 数组呢?

    • dp[i] < dp[j]+1 时说明以此数字结尾的最长子序列长度更新了,那么这样长度的个数就是以 nums[j] 为结尾的最长子序列的个数。即 count[i] = count[j]
    • dp[i] == dp[j]+1 时说明最长长度没有更新但是个数增加了,要加上以 nums[j] 为结尾的最长子序列的个数,即 count[i] += count[j]
  • 在更新 dp数组 的同时可以顺便找到最大子序列长度 max_length

  • 最后遍历dp,找到所有与 max_length 相等的 dp[i],将他们的 count 的累加,即 res += count[i]

class Solution:
    def findNumberOfLIS(self, nums: List[int]) -> int:
        n = len(nums)
        if n == 1:
            return 1
        dp = [1] * n
        count = [1] * n
        max_length = 0
        for i in range(1,n):
            for j in range(i):
                if nums[i] > nums[j]:
                    if dp[j] + 1 > dp[i]:
                        dp[i] = dp[j] + 1
                        count[i] = count[j]
                    elif dp[i] == dp[j]+1:
                        count[i] += count[j]
                max_length =max(max_length,dp[i])
        res = 0
        for i in range(n):
            if dp[i] == max_length:
                res += count[i]
        return res
posted on 2021-09-20 19:28  墩墩儿er  阅读(52)  评论(0)    收藏  举报