这周学了动态规划,我浏览leetcode的题目时,发现了一道和课上讲的题目名字很像的一道题。
一开始我以为是寻找最长子序列的长度就好,结果定睛一看:不是!!是寻找最长子序列的个数。这完全就不是一道题了,这在寻找最大长度的基础上加大了难度。
首先贴出来原题
我的思路是从我错误的例子中找出来的。我发现了一个很有趣的测试样例是:1,1,1,2,2,2,3,3,3.
可以发现这个最长子序列肯定是:1,2,3;而个数是27个。这个个数怎么算出来的呢,无疑是3*3*3.换个说法就是因为每个2都可以选择一个1来作为它的前一个数,所以每个2都有三种选择,每个3又可以选择一个2作为它的前一个数,所以每个3有3*3种选择(因为可以随便选一个2,每个2又可以随便选一个1)。所以三个3就有3*3*3种选择。
所以我的思路就是,每个数都要统计一下它的前一个数的可选个数,然后把它前一个数的可选个数吸收,加到自己的可选个数上。就例如统计3的可选个数是3+3+3(加了3个2的可选个数)。
#include<vector>
#include<iostream>
using namespace std;
class Solution {
public:
int findNumberOfLIS(vector<int>& nums) {
if (nums.size() == 0)
return 0;
for (int i = 0; i < nums.size(); i++) {
L.push_back(0);
}
int count = 0;
int max_index = 0;
//记录有多少个比它长度小1的元素
vector<int> less_count;
for (int i = 0; i < nums.size(); i++) {
int max = L[i];
if (i != 0)
for (int j = 0; j < i; j++) {
if (L[j] > max&&nums[i] > nums[j])
{
max = L[j];
}
}
//记录长度
L[i] = max + 1;
//如果是当前长度为1,也就是第一个元素,less_count设为1
if (L[i] == 1)
less_count.push_back(1);
//其余的设为0
else
less_count.push_back(0);
//记录最大长度的元素位置
if (L[i] >= L[max_index])
max_index = i;
for (int j = 0; j < i; j++) {
//如果长度比它小1且值比它小,那么这个元素的less_count就加上比它小1的元素的less_count
if (L[i] == L[j] + 1 && nums[i] > nums[j])
less_count[i] += less_count[j];
}
}
//把所有长度最大的元素的less_count加起来,就是最后的数目
for (int i = 0; i < nums.size(); i++) {
if (L[i] == L[max_index])
count += less_count[i];
}
return count;
}
private:
vector<int> L;
};
时间复杂度为:O(n*n)遍历中套着一层遍历
空间复杂度为:O(n)记录每个元素的可选个数