leetcode 673. Number of Longest Increasing Subsequence(最长递增子序列的个数)解法 python

一.问题描述

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.

二.解题思路

额,很明显又是一道动态规划题,最近写动态规划题目写的我都要怀疑人生了。。。

动态规划主要还是确定递推的规则

先分析一下题目,

假如我知道从数组的[0,k]中最长的子序列长度是t,个数是m

来分析一下把数组的array[k+1]加进去考虑的时候会发生什么事情

我们只要知道最长的子序列的个数,所有首先考虑什么情况下会给变最长子序列的个数

第一个是:最长子序列的长度+1,这种情况下,最长子序列的个数等于之前所有子序列长度为m的序列中,array[k+1]大于那个子序列的最大值

第二个是:最长子序列的长度不变,个数增加,这种情况就比较复杂,增加的子序列的个数是,(1)之前子序列长度为m-1的序列中,array[k+1]大于那个子序列的最大值;或者(2)在子序列长度为m的序列中,array[k+1]等于那个子序列的最大值,此时子序列的最大值等于m加上满足上述条件的子序列的个数

不管是哪个情况,改变的条件都是要当前的数作为一个序列的结尾,它不能做结尾的时候不能改变任何东西,而做结尾的条件就是它要比之前的数大。

因此,这道题需要两个数组

len[i]: 以数组开始到以num[i]为结尾(注意,是以num[i]为子序列的结尾)的最长子序列长度

cnt[i]:以数组开始到以num[i]为结尾(注意,是以num[i]为子序列的结尾)的最长子序列长度的个数

同时每次迭代maxlen记录最长的序列的长度,res用来记录以maxlen为最长度的序列个数

我们来看看具体怎么迭代的:

当k->k+1时,

我们要比较0~k范围内的数和array[k+1]的值大小,因为之前提到了,array[k+1]结尾才能改变东西

如果数比array[k+1]大,我们不用做处理

如果比array[k+1]小,这是我们重点关注了

首先,如果len[i]+1=len[k+1],这符合我们第二种情况的(1),我们让cnt[k+1]=cnt[k+1]+cnt[i]

如果len[i]+1>len[k+1],len[k+1]=len[i]+1,意思就是把自己加到末尾,cnt[k+1]=cnt[i],对应第一种情况

可能有人会问第二种情况的(2)呢

这是在实现的时候取巧自动处理,利用maxlen和res

如果len[k+1]==maxlen ,res=res+cnt[i] 如果历史最大长度和当前的最大长度相等,说明对应的是情况二

否则 res=cnt[i],对应情况1

迭代的时候,如果array[k+1]==array[i] 并且len[k+1]==len[i]==maxlen, 想想是啥情况

res在之前就已经加上了len[i]的cnt[i],所以不用特地在主程序里去判断情况2的(2),当然你要特地去处理也很简单

价格array[k+1]==array[i]的判断就好了

说实话文字描述动态规划还挺痛苦的,没有天赋做老师啊

更多leetcode算法题解法请关注我的专栏leetcode算法从零到结束或关注我

欢迎大家一起套路一起刷题一起ac

三.源码

class Solution:
    def findNumberOfLIS(self, nums: List[int]) -> int:
        # len[i]: the length of the Longest Increasing Subsequence which ends with nums[i].
        # cnt[i]: the number of the Longest Increasing Subsequence which ends with nums[i].
        if nums==[]:
            return 0
        length=len(nums)
        lens,cnt=[0]*length,[0]*length
        maxlen=0
        lens[0],cnt[0],res=1,1,0
        for i in range(length):
            lens[i],cnt[i]=1,1
            for t in range(0,i):
                if nums[i]>nums[t]:
                    if lens[i]>lens[t]+1:continue
                    if lens[i]==lens[t]+1:cnt[i]+=cnt[t]
                    else:
                        lens[i]=lens[t]+1
                        cnt[i]=cnt[t]
            if maxlen==lens[i]:res+=cnt[i]
            elif maxlen<lens[i]:
                maxlen=lens[i]
                res=cnt[i]
            else:pass
        return res
                
                
                
        

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值