Longest Increasing Subsequence

medium1D Dynamic Programming97 stepsJava · Python · C++

Find the length of the longest strictly increasing subsequence in O(n log n). Keep tails, where tails[k] is the smallest possible tail of an increasing subsequence of length k+1. For each number, binary-search the first tail ≥ it and replace it (or append if none).

▶ Watch the animated trace

Traced input: nums = [10, 9, 2, 5, 3, 7, 101, 18] → 4. Original problem: neetcode.io/problems/longest-increasing-subsequence

Complexity

BestO(n log n)
AverageO(n log n)
WorstO(n log n)
SpaceO(n)

One binary search per element. The O(n²) DP is the simpler alternative.

Key idea

Common mistakes

Solution

Java
int lengthOfLIS(int[] nums) {
    int[] tails = new int[nums.length];
    int size = 0;
    for (int i = 0; i < nums.length; i++) {
        int x = nums[i];
        int lo = 0, hi = size;
        while (lo < hi) {
            int mid = (lo + hi) / 2;
            if (tails[mid] < x) lo = mid + 1;
            else hi = mid;
        }
        tails[lo] = x;
        if (lo == size) size++;
    }
    return size;
}
Python
def lengthOfLIS(nums: List[int]) -> int:
    tails = []
    for x in nums:
        i = bisect.bisect_left(tails, x)
        if i == len(tails): tails.append(x)
        else: tails[i] = x
    return len(tails)
C++
int lengthOfLIS(vector<int>& nums) {
    vector<int> tails;
    for (int x : nums) {
        auto it = lower_bound(tails.begin(), tails.end(), x);
        if (it == tails.end()) tails.push_back(x);
        else *it = x;
    }
    return tails.size();
}

Edge cases

Each one has its own trace in the interactive view.

CaseInputAnswer
All equal
Strictly increasing, so equal values don't extend.
nums = [7, 7, 7, 7]1
Strictly decreasing
Each number replaces the only tail.
nums = [5, 4, 3, 2]1
Already sorted
Every number appends.
nums = [1, 2, 3, 4]4
Single element
Length 1.
nums = [0]1
← Coin ChangeWord Break →