Number of Longest Increasing Subsequences
Solve this ProblemTest Case 1:
Test Case 2:
Test Case 3:
Constraints
- ◆
1 ≤ nums.length ≤ 12 - ◆
-1000 ≤ nums[i] ≤ 1000
Try the Dry Run
Don't just read the solution — watch it execute, one step at a time.
Approach & Solutions
Brute Force — Recursive Without Memoization
BruteExtend the plain skip/take LIS recursion so that, instead of returning just the best length reachable from here, every call returns a pair: the best length, and how many different ways that best length is achieved. At each index, both skipping it and (when the ordering allows) taking it get explored recursively, and each of those returns its own best-length/way-count pair. Whichever option reaches the greater length wins outright, contributing only its own way-count; but if the two options tie on length, both are equally valid, so their way-counts add together. Nothing here is cached, so the same sub-problem is re-solved, and re-counted, every time a different earlier choice happens to land on it again.
O(2^n)O(n)1class Solution {
2 private int[] nums;
3
4 public int findNumberOfLIS(int[] nums) {
5 this.nums = nums;
6 int[] result = solve(0, -1);
7 return result[1];
8 }
9
10 private int[] solve(int i, int prev) {
11 if (i == nums.length) return new int[]{0, 1};
12 int[] skip = solve(i + 1, prev);
13 int takeLen = -1, takeCount = 0;
14 if (prev == -1 || nums[i] > nums[prev]) {
15 int[] sub = solve(i + 1, i);
16 takeLen = 1 + sub[0];
17 takeCount = sub[1];
18 }
19 if (takeLen > skip[0]) return new int[]{takeLen, takeCount};
20 if (takeLen == skip[0]) return new int[]{takeLen, takeCount + skip[1]};
21 return skip;
22 }
23}Optimal — Bottom-Up DP with Length and Count
OptimalKeep two tables alongside each other: len[i], the length of the longest increasing subsequence ending exactly at index i (same as the plain LIS table), and cnt[i], how many distinct subsequences of that specific length end there. For every earlier index j with a smaller value, extending through j is possible. When that extension would make a strictly longer chain than anything seen for i so far, it becomes the new best, and i inherits j's way-count outright. When it only matches the current best length, j's way-count gets added on top, since both are equally valid routes to that same length. Once every index is filled in, the overall longest length is whatever the largest len[] value is, and the final answer sums cnt[i] over every index that actually reaches that length — since the true longest subsequence could end at more than one place.
O(n²)O(n)1class Solution {
2 public int findNumberOfLIS(int[] nums) {
3 int n = nums.length;
4 int[] len = new int[n];
5 int[] cnt = new int[n];
6 Arrays.fill(len, 1);
7 Arrays.fill(cnt, 1);
8 for (int i = 1; i < n; i++) {
9 for (int j = 0; j < i; j++) {
10 if (nums[j] < nums[i]) {
11 if (len[j] + 1 > len[i]) {
12 len[i] = len[j] + 1;
13 cnt[i] = cnt[j];
14 } else if (len[j] + 1 == len[i]) {
15 cnt[i] += cnt[j];
16 }
17 }
18 }
19 }
20 int maxLen = 0;
21 for (int i = 0; i < n; i++) maxLen = Math.max(maxLen, len[i]);
22 int total = 0;
23 for (int i = 0; i < n; i++) {
24 if (len[i] == maxLen) total += cnt[i];
25 }
26 return total;
27 }
28}