最长递增子序列的个数 动态规划

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

给定一个未排序的整数数组 nums  返回最长递增子序列的个数 

注意 这个数列必须是 严格 递增的。

示例 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数组,并且是同样的状态转移方程来更新计算出i结尾的最长子序列的长度,用dp[i]表示,这个方法和这篇里写的一样,后面代码其实也就是在这篇的解决办法上加了点操作。

  具体加的操作是额外的一个count数组,count[i]表示以i位置结尾的最长递增子序列的个数。我们开启两层循环去遍历数组,外层用i,内层用j,j<i, 为了得到递增子序列,我们只考虑nums[i]>nums[j]时的情况,此时我们判断dp[i]dp[j]+1的关系:

  1.如果dp[i]<dp[j]+1,就说明i当前的位置可以被当作新的更大值,dp[i]可以被更新到更大,我们去更新dp;同时count[i]等于count[j],因为不管以j结尾的最长递增子序列的个数是多少个,再多算上它i还是多少个。(此时的count[i]只是初始化结束,后续还要进行下面的加等于操作。)

  2.如果dp[i]==dp[j]+1,此时说明dp[i]已经被更新到了最大值,此时不需要去更新dp;但要让count[i]加等于count[j],因为此时以j为结尾的所有最长递增子序列又可以去加上i组成新的。

代码:

class Solution(object):
    def findNumberOfLIS(self, nums): 
        lenth=len(nums)
        dp=[1]*lenth    #dp[i] 以i结尾的最长子序列的长度
        count=[1]*lenth #count[i] 以i结尾的最长子序列的个数
        for i in range(1,lenth):#两层循环遍历dp数组
            for j in range(i):
                if nums[i]>nums[j]:#只有当nums[i]>nums[j]才进行dp的更新和判断
                    # 如果dp[j] + 1 > dp[i],说明最长递增子序列的长度增加了
                    if dp[i]<dp[j]+1:
                        #dp[i]更新为dp[j] + 1,重新初始化 count[i] = count[j]
                        dp[i]=dp[j]+1
                        count[i]=count[j]
                #如果dp[j]+1==dp[i]说明dp[i]已经更新到当前最大但又出现了一样的dp[j]
                    elif dp[i]==dp[j]+1:
                        #直接增加 count[i] += count[j]
                        count[i]+=count[j]
        maxx=max(dp)#先找到最大长度
        res = 0
        for i,d in enumerate(dp):
            if d==maxx:#找到所有最大长度的位置
                res+=count[i]#把这个位置对应的个数加到结果里去
        return res

小结:

  我感觉这道题应该算是困难题了(虽然写的是中等难度),我确实觉得这个dp思路确实不管是写起来还是理解起来都比较困难。可以尝试只看我的代码,或许就直接懂了。

  最后再对思路做个小补充:我们不能一开始就初始化count[i]=0然后两种情况都用count[i]加等于count[j],因为这样会把不是最长递增子序列的个数都加进来。第一种情况不用count[i]加等于count[j]是为了一旦遇到更长的最长递增序列,我们就要重新初始化为count[j]

posted @   JunanP  阅读(7)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示