题目
给定一个未排序的整数数组,找到最长递增子序列的个数。
示例 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
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路:动态规划
基本的思路和 Leetcode 300. 最长递增子序列 一样,这里用动态规划求解。在 300 那个题里面,只需要一个动态规划数组来保存以 nums[i]
结尾的最长递增子序列长度即可,也就是代码中的 dpLen
;在这个题里面需要一个额外的数组来保存以 nums[i]
结尾的最长递增子序列的个数,也就是代码中的 dpCnt
在用
j
j
j 遍历
[
0
,
i
)
[0,i)
[0,i) 更新 dpLen
的同时,要检查是否出现了更长的序列,如果有,就直接覆盖掉 dpCnt[i]
,如果序列长度和之前的一致,就应该累加 dpCnt[i]
注意 dpLen
和 dpCnt
中的元素不小于 1,因为至少也有 nums[i]
自身组成的长度为 1 的序列,数量是 1
时间复杂度:
O
(
n
2
)
O(n^2)
O(n2)
空间复杂度:
O
(
n
)
O(n)
O(n)
C++ 代码
class Solution {
public:
int findNumberOfLIS(vector<int>& nums) {
if (nums.empty())
return 0;
vector<int> dpLen(nums.size(), 0);
vector<int> dpCnt(nums.size(), 0);
dpLen[0] = 1;
dpCnt[0] = 1;
for (int i = 1; i < nums.size(); ++i) {
for (int j = 0; j < i; ++j) {
if (nums[j] < nums[i]) {
if (dpLen[j] + 1 > dpLen[i]) {
dpLen[i] = dpLen[j] + 1;
dpCnt[i] = dpCnt[j];
} else if (dpLen[j] + 1 == dpLen[i]) {
dpCnt[i] += dpCnt[j];
}
}
}
dpLen[i] = dpLen[i] == 0 ? 1 : dpLen[i];
dpCnt[i] = dpCnt[i] == 0 ? 1 : dpCnt[i];
}
int ans = 0;
int maxLen = *max_element(dpLen.begin(), dpLen.end());
for (int i = 0; i < nums.size(); ++i) {
if (dpLen[i] == maxLen) {
ans += dpCnt[i];
}
}
return ans;
}
};