定义状态
- length[i]:到nums[i]为止的最长递增子序列长度
- count[i]:到nums[i]为止的最长递增子序列个数
初始化状态
- length = [1] * n:代表最长递增子序列的长度至少为1
- count = [1] * n:代表最长递增子序列的个数至少为1
状态转移
对于每一个以nums[i]结尾的序列,比较nums[i],nums[j]。
如果j>i, nums[j] > nums[i],
那么相当于到nums[i]为止的最长递增子序列长度在nums[j]时增加了1,到nums[j]为止的最长递增子序列长度就变成了length[j] = length[i] + 1;
但是因为满足nums[j] > nums[i] 的nums[i]不止一个,length[j]应该取这些length[i] + 1的最大值,并且这些length[i] + 1还会有相等的情况,一旦相等,到nums[j]为止的最长递增子序列个数count[j]就应该增加count[i]。
因此,具体的状态转移如下,在nums[j] > nums[i]的大前提下:
- 如果length[i] + 1 > length[j],说明最长递增子序列的长度增加了,length[j] = length[i] + 1,长度增加,数量不变 count[j] = count[i]
- 如果length[i] + 1 == length[j],说明最长递增子序列的长度并没有增加,但是出现了长度一样的情况,数量增加 count[j] += count[i]
记录最长递增子序列的最大长度maxlen
遍历length数组,如果length数组记录的最大长度length[index]等于maxlen,将对应的数量count[index]加到结果ans中。
代码:
class Solution {
public int findNumberOfLIS(int[] nums) {
int n = nums.length;
if (n == 0)
return 0;
int[] length = new int[n];
int[] count = new int[n];
Arrays.fill(length, 1);
Arrays.fill(count, 1);
int maxlen = 1;
for (int j = 1; j < n; j++){
for (int i = 0; i < j; i++){
if (nums[j] > nums[i]){
if (length[i] + 1 > length[j]){
length[j] = length[i] + 1;
count[j] = count[i];
}else if (length[i] + 1 == length[j]){
count[j] += count[i];
}
}
}
maxlen = Math.max(length[j], maxlen);
}
int ans = 0;
for (int index = 0; index < n; index++){
if (length[index] == maxlen){
ans += count[index];
}
}
return ans;
}
}
复杂度分析
时间复杂度:O(
n
2
n ^ 2
n2)
空间复杂度:O(n)