给定一个未排序的整数数组,找到最长递增子序列的个数。
示例 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。
注意: 给定的数组长度不超过 2000 并且结果一定是32位有符号整数。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/number-of-longest-increasing-subsequence
参考:
python
# 0673.最长递增子序列的个数
class Solution:
def findNumOfLIS(self, nums: [int]) -> int:
"""
动态规划
1.dp定义及下标
- dp[i], i为下标的最长递增子序列的长度
- count[i], nums[i]结尾的,最长递增子序列个数为count[i]
2.递推公式
两个维度,
- 更新dp[i], if (nums[i] > nums[j]) dp[i] = max(dp[i], dp[j] + 1)
- 更新count[i]
- 在nums[i] > nums[j]前提下,如果在[0, i-1]的范围内,找到了j,使得dp[j] + 1 > dp[i],说明找到了一个更长的递增子序列。
那么以j为结尾的子串的最长递增子序列的个数,就是最新的以i为结尾的子串的最长递增子序列的个数,即:count[i] = count[j]。
- 在nums[i] > nums[j]前提下,如果在[0, i-1]的范围内,找到了j,使得dp[j] + 1 == dp[i],说明找到了两个相同长度的递增子序列。
那么以i为结尾的子串的最长递增子序列的个数 就应该加上以j为结尾的子串的最长递增子序列的个数,即:count[i] += count[j]
3.初始化
- dp[i] = 1
- count[i] = 1
4.遍历顺序
- 外层for 1->length-1
- 内层for 0, i-1
:param nums:
:return:
"""
length = len(nums)
if length <= 1: return length
dp = [1 for i in range(length)]
count = [1 for i in range(length)]
maxCnt = 0
for i in range(1, length):
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[j] + 1 == dp[i]:
count[i] += count[j]
if dp[i] > maxCnt:
maxCnt = dp[i]
res = 0
for i in range(length):
if maxCnt == dp[i]:
res += count[i]
return res
golang
package dynamicPrograming
// 动态规划
func findNumberOfLIS(nums []int) int {
length := len(nums)
if length <= 1 {
return length
}
dp := make([]int, length)
count := make([]int, length)
for i := range dp {
dp[i] = 1
count[i] = 1
}
maxCnt := 0
for i:=1;i<length;i++ {
for j:=0;j<i;j++ {
if nums[i] > nums[j] {
if dp[j] +1 > dp[i] {
dp[i] = dp[j] + 1
count[i] = count[j]
} else if dp[j] + 1 == dp[i] {
count[i] += count[j]
}
}
if dp[i] > maxCnt {
maxCnt = dp[i]
}
}
}
res := 0
for i := range dp {
if maxCnt == dp[i] {
res += count[i]
}
}
return res
}