描述:求最长公共子序列的数量:
example1:
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.
最开始的思路是才用bfs的思路维持一个大顶堆,记录每一层的节点数,最后将每层的节点数相乘即为最长公共子序列的长度,如左图:
当大顶堆中的最大值小于数组中的下一个值时,res = res * size(大顶堆),然后清空大顶堆
但是这种情况不满足:1,2,4,35,4,7,2
参考leetcode中discussion中的两种做法:
1)动态规划:保留两个动态规划数组,分别存储最大递增子序列的长度和最长递增子序列的数量
class Solution {
public:
int findNumberOfLIS(vector<int>& nums) {
int size = nums.size();
if(size < 2)
return size;
vector<int> dp(size, 1);
vector<int> dpfreq(size, 1);
int longest = 0;
int res = 0;
for(int i = 1; i < size; i++)
{
for(int j = 0; j < i; j++)
{
if(nums[i] > nums[j])
{
if(dp[i] == dp[j] + 1)
{
dpfreq[i] += dpfreq[j];
}
else if(dp[i] < dp[j] + 1)
{
dp[i] = dp[j] + 1;
dpfreq[i] = dpfreq[j];
}
}
}
if(dp[i] == longest)
res += dpfreq[i];
if(dp[i] > longest)
{
longest = dp[i];
res = dpfreq[i];
}
}
if(longest == 1)
return size;
return res;
}
};
2) 深度优先搜索:
class Solution {
public:
int findNumberOfLIS(vector<int>& nums) {
if(nums.empty()) return 0;
unordered_map<int, int>m;
int maxlen = 1;
for(int i = 0; i < nums.size(); i++)
DFS(nums, i, m, 1, maxlen);
return m[maxlen];
}
void DFS(vector<int>& nums, int k, unordered_map<int, int>& m, int len, int& maxlen){
maxlen = max(maxlen, len);
if(len == maxlen) m[len]++;
for(int i = k + 1; i < nums.size(); i++)
if(nums[i] > nums[k]) DFS(nums, i, m, len + 1, maxlen);
}
};