动态规划思想

注意:子串和子序列的区别

子串一定时连续的,子序列不一定是连续的

最长上升子序列的长度&最长上升子序列的个数(动态规划)_初始化

首先清楚dp数组的含义

定义:dp[i]表示以nums[i]这个数结尾的最长递增子序列的长度

最长上升子序列的长度&最长上升子序列的个数(动态规划)_子串_02

 

因为nums[3]=4,最长递增子序列为1,3,4,所以长度为3即dp[3]=3

既然是递增子序列,只要找到前面那些结尾比4小的子序列,然后把4接到最后,就可以形成一个新的递增子序列,长度加1

class Solution:
    def lengthOfLIS(self, nums: List[int]) -> int:
        # 初始化dp数组为1
        dp = [1] * len(nums)
        for i in range(len(nums)):
            for j in range(i):
                if nums[i] > nums[j]:
                    dp[i] = max(dp[i], dp[j]+1)
        
        res = 0
        for i in range(len(dp)):
            res = max(res, dp[i])
        return res

  最长上升子序列的长度&最长上升子序列的个数(动态规划)_子串_03

 

class Solution:
    def findNumberOfLIS(self, nums: List[int]) -> int:
        if not nums:
           return 0
        # length表示以x为结尾的最长递增子序列的长度
        length = [1 for _ in range(len(nums))] 
        # count 表示以x为结尾的最长递增子序列的个数
        count = [1 for _ in range(len(nums))]
        for i in range(len(nums)):
            for j in range(i):
                if nums[i] > nums[j]:
                    # 在初始化的length表基础上,正常都是length前面的值小于等于length后面的值(初始化为1)
                    if length[j] >= length[i]:
                        length[i] = length[j] + 1
                        count[i] = count[j]
                # 如果遇到这个i前面两个相同的值,第二次进入这个条件时,这个i已经是做过length[i] = length[j] + 1,即有两个长度相同的子序列
                    elif length[j] + 1 == length[i]:
                        count[i] += count[j]

        res = 0
        # 找最长递增子序列,要在length中找长度最长的子序列个数之和
        maxSub = max(length)
        for i in range(len(nums)):
            if length[i] == maxSub:
                res += count[i]
        return res