赞
踩
给定一个未排序的整数数组,找到最长递增子序列的个数。
- 输入:
[1, 3, 5, 4, 7]
- 输出: 2 2 2
- 解释: 有两个最长递增子序列,分别是
[1, 3, 4, 7]
和[1, 3, 5, 7]
。
- 输入:
[2, 2, 2, 2, 2]
- 输出: 5 5 5
- 解释: 最长递增子序列的长度是 1 1 1,并且存在 5 5 5 个子序列的长度为 1 1 1 ,因此输出 5 5 5 。
- 来源: 力扣(LeetCode)
- 链接: https://leetcode-cn.com/problems/number-of-longest-increasing-subsequence
给定的数组长度不超过 2000 2000 2000 并且结果一定是 32 32 32 位有符号整数。
- 作者: edelweisskoko
dp[i]
:到 nums[i]
为止的最长递增子序列长度;count[i]
:到 nums[i]
为止的最长递增子序列个数。dp = [1] * n
:代表最长递增子序列的长度至少为
1
1
1 ;count = [1] * n
:代表最长递增子序列的个数至少为
1
1
1 。对于每一个数 nums[i]
,看在它之前的数 nums[j]
(
0
≤
j
<
i
0 \le j \lt i
0≤j<i)是否比当前数 nums[i]
小:
nums[i] > nums[j]
,那么相当于到 nums[j]
为止的最长递增子序列长度到 nums[i]
增加了
1
1
1,到 nums[i]
为止的最长递增子序列长度就变成了 dp[i] = dp[j] + 1
;nums[i] > nums[j]
的 nums[j]
不止一个,dp[i]
应该取这些 dp[j] + 1
的最大值,并且这些 dp[j] + 1
还会有相等的情况,一旦相等,到 nums[i]
为止的最长递增子序列个数就应该增加了。因此,具体的状态转移如下,在 nums[i] > nums[j]
的大前提下:
dp[j] + 1 > dp[i]
,说明最长递增子序列的长度增加了,dp[i] = dp[j] + 1
,长度增加,数量不变 count[i] = count[j]
;dp[j] + 1 == dp[i]
,说明最长递增子序列的长度并没有增加,但是出现了长度一样的情况,数量增加 count[i] += count[j]
。最终,将所有最长递增子序列的个数加在一起即为最终结果。
from typing import List class Solution: @classmethod def find_num_of_lis(cls, nums: List[int]) -> int: dp = [1] * len(nums) count = [1] * len(nums) max_length = 0 num = 0 for i in range(len(nums)): 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] max_length = max(dp) for k in range(len(nums)): if dp[k] == max_length: num += count[k] return num def main(): # nums = [1, 3, 5, 4, 7] nums = [2, 2, 2, 2, 2] sln = Solution() print(sln.find_num_of_lis(nums)) # 5 if __name__ == '__main__': main()
- 执行用时: 876 ms , 在所有 Python3 提交中击败了 82.00% 的用户;
- 内存消耗: 15.1 MB , 在所有 Python3 提交中击败了 86.19% 的用户。
实际上,最后用于返回结果的代码可以进一步简化:
from typing import List class Solution: @classmethod def find_num_of_lis(cls, nums: List[int]) -> int: dp = [1] * len(nums) count = [1] * len(nums) num = 0 for i in range(len(nums)): 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] max_length = max(dp) return sum(c for i, c in enumerate(count) if dp[i] == max_length) def main(): # nums = [1, 3, 5, 4, 7] nums = [2, 2, 2, 2, 2] sln = Solution() print(sln.find_num_of_lis(nums)) # 5 if __name__ == '__main__': main()
- 时间复杂度: O ( n 2 ) O(n^2) O(n2) 。其中 n n n 是
nums
的长度。- 空间复杂度: O ( n ) O(n) O(n),
dp
和count
所用的空间。
- 作者: Dmitry DBabichev
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。