Skip to main content
Medium Dynamic Programming High frequency

Longest Increasing Subsequence

Open on LeetCode

Approach Summary

Patience sorting with binary search: maintain a tails array. Binary search to find where each element goes.

Full Solution & Approach

The classic O(n²) DP defines dp[i] as the length of the longest increasing subsequence ending at index i, computed as 1 + max(dp[j]) over all j < i with nums[j] < nums[i]. The O(n log n) version is the interview favorite: maintain a tails array where tails[k] is the smallest possible tail value of an increasing subsequence of length k + 1. For each number, binary search for the first tails entry that is at least the number and replace it; if the number is larger than everything, append it. The length of tails is the answer. Replacing entries does not lose solutions — it only keeps the best (smallest) tail for each length, which dominates larger tails. This patience-sorting technique is subtle but is the standard expected solution for the n up to 10⁵ constraints.

Each element performs one binary search over the tails array — O(n log n) time. The tails array grows to at most n — O(n) space.

Solution Code

Solution

import bisect

def length_of_lis(nums: list[int]) -> int:
    tails = []
    for n in nums:
        i = bisect.bisect_left(tails, n)
        if i == len(tails):
            tails.append(n)
        else:
            tails[i] = n
    return len(tails)

Edge Cases to Watch

  • Empty array — return 0
  • Strictly decreasing array — LIS length 1
  • All equal values — LIS length 1 (strict inequality required)
  • Already increasing array — the answer is the full length

How to Recognize This Pattern

  • LIS length
  • Strictly increasing subsequence

Complexity Analysis

Time Complexity

O(n log n)

Space Complexity

O(n)

Tags

Array DP Binary Search

This site is free. If these guides are helping your prep, consider buying me a coffee. ☕

Support →
Buy me a coffee