Description
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.
Explain
最近都会做动态规划的题,毕竟动态规划的核心思想是
状态
和 状态方程
。当前的状态依赖上一个状态,我们要解这类题就得找出状态转移方程,放在高中就是递推公式。而这道题,和LIS挺类似的。这道题不是求最长递增子串的长度了,是求它的数量了。而我们求出当前的最长长度时,那它的数量就是 maxLen - 1 的数量和,状态转移方程就出来了:dpp[i] = max(dpp[i], dpp[j]+...+dpp[k])(j...k 为dp值为dp[i] - 1的下标)
。那么我们就可以用一个dpp数组来记录对应的数量,最后算出最长长度时,遍历一遍数组将dp[i]为最大值的对应的dpp[i]相加就得出结果了。还是看代码吧
Code
class Solution {
public:
int findNumberOfLIS(vector<int>& nums) {
if (nums.empty()) return 0;
int res = 0;
int maxx = INT_MIN;
vector<int> dp(nums.size(), 1);
vector<int> dpp(nums.size(), 1);
for (int i = 0; i < nums.size(); i++) {
int count = 0;
for (int j = 0; j < i; j++) {
if (nums[i] > nums[j]) {
dp[i] = max(dp[j] + 1, dp[i]);
}
}
for (int j = 0; j < i; j++) {
if (dp[i] == 1) count = 1;
else if (dp[j] == dp[i] - 1 && nums[j] < nums[i]) {
count += dpp[j];
}
}
dpp[i] = max(dpp[i], count);
maxx = max(maxx, dp[i]);
}
for (int i = 0; i < nums.size(); i++) {
if (maxx == dp[i]) res += dpp[i];
}
return res;
}
};