Skip to main content

Number of Longest Increasing Subsequence

Problem

Given an integer array nums, return the number of longest increasing subsequences.

Notice that the sequence has to be strictly increasing.

 

Example 1:

Input: nums = [1,3,5,4,7]
Output: 2
Explanation: The two longest increasing subsequences are [1, 3, 4, 7] and [1, 3, 5, 7].

Example 2:

Input: nums = [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.

 

Constraints:

  • 1 <= nums.length <= 2000
  • -106 <= nums[i] <= 106

Solution

/**
* @param {number[]} nums
* @return {number}
*/
var findNumberOfLIS = function(nums) {
let max = 1; // overall max length of subsequence
let count = 1; // overall count of max length subsequence
const dp = [{ max, count }];

for (let i = 1; i < nums.length; i++) {
dp.push({ max: 1, count: 1 });
for (let j = 0; j < i; j++) {
if (nums[i] > nums[j]) { // can end at nums[i]
if (dp[i].max < dp[j].max + 1) { // new local max
dp[i].max = dp[j].max + 1;
dp[i].count = dp[j].count;
} else if (dp[i].max === dp[j].max + 1) { // same local max
dp[i].count += dp[j].count;
}
}
}
if (dp[i].max > max) { // new global max => new global count
max = dp[i].max;
count = dp[i].count;
} else if (dp[i].max === max) { // same global max => increment global count
count += dp[i].count;
}
}
return count;
};

We will implement a DP solution. Let dp[i] have two properties, max and count. Let dp[i].max be the length of the longest increasing subsequence ending at and including nums[i]. Let dp[i].count be the number of increasing subsequences of length dp[i].max ending at and including nums[i].

  • For the base case, if i = 0, then dp[0].max = 1 and dp[0].count = 1 since there's only 1 possible subsequence which is nums[0] itself.
  • For the recursive case, dp[i].max is computed the same way as the Longest Increasing Subsequence problem. For dp[i].count:
    • When we encounter a new subsequence with length greater than dp[i].max, we update dp[i].count to the count of the previous value in this new subsequence (ie. dp[i].count will be reset to dp[j].count since the old count is no longer relevant for the new max length subsequence).
    • When we encounter a new subsequence with length same as dp[i].max, we increment dp[i].count by the count of the previous value in this new subsequence (ie. dp[i].count will be incremented by dp[j].count since the old count is still relevant).

Note that we also keep an overall max and count variable and update the two as needed after every i (in a similar manner as the recursive case for dp).