Number of Longest Increasing Subsequence

MediumDynamic Programming · LIS · Fenwick Tree🧩 Longest Increasing SubsequenceLeetCode #673 ↗Updated

Problem

Given an integer array nums, find the length L of its longest strictly increasing subsequence, and return how many different subsequences have length L. Subsequences are distinguished by the indices they use, so equal values at different positions count separately.
Inputnums = [1,3,5,4,7]Output2 ([1,3,5,7] and [1,3,4,7])
Inputnums = [2,2,2,2,2]Output5 (each single element)

1 ≤ n ≤ 2000  ·  -106 ≤ nums[i] ≤ 106  ·  the answer fits in a 32-bit int

Try it yourself

Java
class Solution {
    public int findNumberOfLIS(int[] nums) {
        
    }
}
Your code is saved in this browser.Submit on LeetCode ↗
Key insight
Track two numbers per index: len[i], the longest increasing run ending at i, and cnt[i], how many runs reach that length. When extending from j, a longer length replaces the count; an equal length adds to it.
PatternLongest Increasing Subsequence

Instinct Longest chain where each pick must beat the last (bigger, later, fits inside) - O(n²) best-ending-here DP, or O(n log n) tails plus binary search.

Memory hack Patience solitaire - drop each card on the leftmost pile whose top is not smaller; the number of piles is the LIS length.

Open the Longest Increasing Subsequence guide →

Approaches

Brute ForceRecursion: Longest Runs Starting at Each Index

Time O(n · 2n)Space O(n)

For a start index i, recursively try every next index j > i with a bigger value and combine the children's (length, count) pairs: keep the longest, summing counts on ties. Without caching, every increasing subsequence is walked separately.

Java
public int findNumberOfLIS(int[] nums) {
    int bestLen = 0, total = 0;
    for (int i = 0; i < nums.length; i++) {
        int[] r = longestFrom(nums, i);
        if (r[0] > bestLen) { bestLen = r[0]; total = r[1]; }
        else if (r[0] == bestLen) total += r[1];
    }
    return total;
}

// {length, count} of the longest increasing subsequences starting at i
private int[] longestFrom(int[] nums, int i) {
    int len = 1, cnt = 1;
    for (int j = i + 1; j < nums.length; j++) {
        if (nums[j] <= nums[i]) continue;
        int[] r = longestFrom(nums, j);
        if (r[0] + 1 > len) { len = r[0] + 1; cnt = r[1]; }
        else if (r[0] + 1 == len) cnt += r[1];
    }
    return new int[]{len, cnt};
}

Shows the (length, count) combine rule, but is exponential.

At a glance

LevelApproachTimeSpace
Brute ForceRecursion: Longest Runs Starting at Each IndexO(n · 2n)O(n)
BetterO(n²) DP with Length and Count ArraysO(n²)O(n)
OptimalFenwick Tree of (length, count) over Value RanksO(n log n)O(n)
Common pitfalls
  • Returning cnt of the last index only — sum over every index with the max length.
  • On a strictly longer extension, assign cnt[i] = cnt[j]; adding double-counts.
  • Using ≤ instead of < lets equal values chain together.
Interview tips
  • Start from classic LIS and say: “I just need a count alongside each length.”
  • Walk the tie-vs-longer rule on [1,3,5,4,7] — it convinces quickly.
  • Mention the Fenwick/segment-tree upgrade only after the O(n²) version is correct.
Pattern
LIS DP with counting → when you need how many optimal subsequences, not just the optimal length.
My notes saved in this browser