Longest Increasing Subsequence

MediumDynamic Programming · LIS · Binary Search🧩 Longest Increasing SubsequenceLeetCode #300 ↗Updated

Problem

Given an integer array nums, return the length of the longest subsequence whose values are strictly increasing. A subsequence keeps the original order but may skip elements (it need not be contiguous).
Input[10,9,2,5,3,7,101,18]Output4 ([2,3,7,18])
Input[0,1,0,3,2,3]Output4
Input[7,7,7,7]Output1

1 ≤ n ≤ 2500  ·  -104 ≤ nums[i] ≤ 104  ·  Follow-up: O(n log n) time.

Try it yourself

Java
class Solution {
    public int lengthOfLIS(int[] nums) {
        
    }
}
Your code is saved in this browser.Submit on LeetCode ↗
Key insight
For each length k keep only the smallest possible tail of an increasing subsequence of length k. These tails are sorted, so each new number either extends the longest one or replaces the first tail ≥ it (binary search).
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 (Take / Skip)

Time O(2n)Space O(n)

Walk the array remembering the index prev of the last taken element. At index i either skip it, or take it if it is larger than nums[prev]. This explores every subsequence.

Java
public int lengthOfLIS(int[] nums) {
    return lis(nums, 0, -1);
}
private int lis(int[] nums, int i, int prev) {
    if (i == nums.length) return 0;
    int skip = lis(nums, i + 1, prev);
    int take = 0;
    if (prev == -1 || nums[i] > nums[prev]) take = 1 + lis(nums, i + 1, i);
    return Math.max(skip, take);
}

Simple and correct, but exponential — hopeless beyond n ≈ 25.

At a glance

LevelApproachTimeSpace
Brute ForceRecursion (Take / Skip)O(2n)O(n)
BetterDP — LIS Ending at Each IndexO(n2)O(n)
OptimalPatience Sorting (Tails + Binary Search)O(n log n)O(n)
Common pitfalls
  • Returning dp[n-1] instead of max(dp) — the LIS may end earlier.
  • Using <= in the binary search — allows equal values (not strictly increasing).
  • Claiming tails is the actual subsequence — only its length is meaningful.
Interview tips
  • Define the DP state precisely: “LIS that ends at i”.
  • Justify the greedy: a smaller tail leaves more room for future elements.
  • To rebuild the sequence, store tail indices plus a parent array.
Pattern
LIS / patience sorting → longest chain under an ordering, often after sorting by one key.
My notes saved in this browser