Browse curriculum

Number of Longest Increasing Subsequence

Count how many strictly increasing subsequences have the maximum length, by tracking for each index both the longest length ending there and how many ways reach it.

Problem Understanding

Number of Longest Increasing Subsequence: given an integer array nums, return the number of longest strictly increasing subsequences.

Examples: [1,3,5,4,7] → 2 ([1,3,4,7] and [1,3,5,7]); [2,2,2,2,2] → 5.

The Intuition: Longest Increasing Subsequence, Plus a Counter

Start from Longest Increasing Subsequence: length[i] is the longest increasing subsequence ending at i. Now also count:

  1. Strictly longer via j: take the new length and replace the count with count[j].
  2. Same length via j: add count[j], more ways to the same best.
  3. Finish: add up count[i] wherever length[i] is the overall maximum.

The same "count the ways to reach the optimum" trick appears in many dynamic programming problems.

Interactive Walkthrough

len = LONGEST ENDING HERE · cnt = HOW MANY REACH IT

len = cnt = 1

nums

1
3
5
4
7

len

1
1
1
1
1

cnt

1
1
1
1
1

longest

1

answer

:

 

Every element alone is an increasing subsequence: len = 1, cnt = 1 everywhere

Next

1 < 3: extending gives length 2, longer than before. len[1] = 2, cnt[1] = cnt[0] = 1

Free preview: the first 4 of 12 steps

nums

Rows show nums, length and count. Index i is filled, the earlier j is marked, and the cells a step changed are highlighted. Try Three ways to see counts add up.

Dry Run Table

Input: [1,3,5,4,7].

i nums[i] length count
0 1 1 1
1 3 2 1
2 5 3 1
3 4 3 1
4 7 4 2 (via 5 and via 4)

Answer: 2.

The Solution Template

Two arrays, one double loop.

Number of Longest Increasing Subsequence Code
1var findNumberOfLIS = function(nums) {
2 const n = nums.length;
3 const length = new Array(n).fill(1), count = new Array(n).fill(1);
4 for (let i = 0; i < n; i++) {
5 for (let j = 0; j < i; j++) {
6 if (nums[j] >= nums[i]) continue;
7 if (length[j] + 1 > length[i]) {
8 length[i] = length[j] + 1;
9 count[i] = count[j];
10 } else if (length[j] + 1 === length[i]) {
11 count[i] += count[j];
12 }
13 }
14 }
15 const longest = Math.max(...length);
16 let total = 0;
17 for (let i = 0; i < n; i++) if (length[i] === longest) total += count[i];
18 return total;
19};

Edge Cases & Common Mistakes

  • All equal values: every element alone is a longest subsequence; the answer is n.
  • Strictly increasing only: use <, not <=.
  • Adding instead of replacing on a longer length: keeps counts of shorter subsequences.
  • Returning count of the last index: the longest subsequences can end anywhere.
  • Single element: answer 1.

Summary

Track length[i] and count[i]; a longer extension replaces the count, an equal one adds to it; sum count[i] where length[i] is the maximum. O(n²) time, O(n) space.

More practice: DSA interview questions with answers · patterns cheat sheet

The approach, step by step

  1. Start

    length[i] = count[i] = 1 for every i.

  2. Extend

    For each j < i with nums[j] < nums[i]: if length[j] + 1 > length[i], set length[i] = length[j] + 1 and count[i] = count[j]; if equal, add count[j].

  3. Answer

    Sum count[i] over every i with length[i] equal to the maximum length.

Frequently asked questions

Why is a second array needed?

The Longest Increasing Subsequence DP only remembers how long the best subsequence ending at i is. To count them you also need how many different subsequences achieve that length; that is count[i], updated alongside length[i].


Why copy count[j] on a longer length but add it on a tie?

A strictly longer length makes every subsequence counted so far at i obsolete: the best ones now all come through j, so count[i] = count[j]. An equal length is just more ways to reach the same best, so count[i] += count[j].


Why sum over every index with the maximum length?

The longest subsequences can end at different positions. Each count[i] covers those ending at i, and different endings are different subsequences, so the answer adds count[i] for every i whose length equals the overall maximum.


Is there something faster than O(n²)?

Yes, O(n log n) with a segment tree or Fenwick tree over compressed values that stores (best length, count) per value and merges them. For LeetCode's n ≤ 2000 the O(n²) DP is the expected answer.

New to the technique behind this problem? Watch it run step by step:

Dynamic Programming Visualization

Applying for software engineering roles? Free, no sign-up:

AI resume checker: match your resume to the job description