LeetCode 673. Number of Longest Increasing Subsequence
2020-06-11 19:55:48 # leetcode # core problems

Problem

LeetCode 673. Number of Longest Increasing Subsequence

1. 题目简述

给出一个未排序的整形数组,返回其最长递增系序列的数量。例如:

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].

Note:

数据规模不会超过2000且保证最终的解是32位整形数

2. 算法思路

相关问题:

  1. LeetCode 300. Longest Increasing Subsequence

和300题不同的是,这里我们需要返回的是数量,而不是长度,也就是说仅仅找出长度已经无法满足我们的需求,我们不仅需要记录长度,还需要记录数量。

另一种思路是使用segement tree,暂时还没学到那块,等学到了在回头看!!!

动态规划

我们需要记录的有两个数值,到当前数字截止的最长的递增子序列长度和数量。因此,这是一个二维dp问题。对于300题中的第二种解法我们可以抛弃了,因为它只能找出长度,而无法找到数量。

因此,我们记录一个二维dp数组,每一维数组都有两个值,一个是长度,一个是数量。

当我们向前一个个查找的时候,记录最长的递增子序列的数量。

时间复杂度为O(n ^ 2),因为每次都要去找前面所有的数字,很慢。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
class Solution {
public int findNumberOfLIS(int[] nums) {
if (nums == null || nums.length == 0) {
return 0;
}

// dp[i][0]表示到当前的最长长度,dp[i][1]表示当前最长长度的数量;初始化dp[0][0] = 0, dp[0][1] = 1。
int n = nums.length;
int[][] dp = new int [n][2];
for (int i = 0; i < n; i++) {
dp[i][0] = 1;
}
dp[0][1] = 1;

int maxLength = 1;
for (int i = 1; i < n; i++) {
// 这里需要注意!!!count需要初始化为1,因为假设说前面都没有比它小的,那么它就不会进入循环,它自己本身就是一个序列。
int count = 1, longestLength = 1;
for (int j = 0; j < i; j++) {
// 只有当前面数字比当前数字小的时候才会进行判断
if (nums[j] < nums[i]) {
if (longestLength < dp[j][0] + 1) {
count = dp[j][1];
longestLength = dp[j][0] + 1;
} else if (longestLength == dp[j][0] + 1) {
count += dp[j][1];
}
}
}
dp[i][0] = longestLength;
dp[i][1] = count;
maxLength = Math.max(maxLength, longestLength);
}

// 根据最长长度遍历dp数组,记录总的最长长度数量
int res = 0;
for (int i = 0; i < n; i++) {
if (dp[i][0] == maxLength) {
res += dp[i][1];
}
}

return res;
}
}