DSA Tracker

Problem

Pattern this teaches:1D Dynamic Programming

Medium

Longest Increasing Subsequence

A medium Dynamic Programming interview guide. Task statement, worked examples, intuition, and step-by-step solutions.

Topic
Dynamic Programming
Sheets
3
Core for
9 roles

The problem

Given an integer array, return the length of the longest strictly increasing subsequence. A subsequence is derived by deleting some or no elements without changing the order of remaining elements.

Example 1

Input
nums = [4,6,2,7,3,8,1,9]
Output
5
Why
Longest increasing subsequence is [4,6,7,8,9] (indices 0,1,3,5,7), length 5.

Example 2

Input
nums = [5,2,8,3,9,1,7]
Output
3
Why
Longest increasing subsequence has length 3, e.g., [2,8,9] or [2,3,9] or [5,8,9].

Example 3

Input
nums = [8,8,8,8,8,8,8]
Output
1
Why
All elements are equal, so the longest strictly increasing subsequence has length 1.

Constraints

  • 1 <= nums.length <= 2500
  • -10^4 <= nums[i] <= 10^4

How to think about it

Updated 2026-09-29

When extending an increasing subsequence, the specific past elements do not matter: only the tail element matters, because smaller tails make room for more future numbers. Keeping track of the smallest possible tail for every subsequence length produces a sorted list of barriers where each new number can be placed via binary search.

Approaches, worst first

  1. Subsequence generation

    time O(2^n) · space O(n)

    Generate all 2^n subsequences, verify which ones are strictly increasing, and track the maximum length. The exponential explosion makes this impossible for n up to 2500.

  2. Prefix maximum scan

    time O(n^2) · space O(n)

    Let dp[i] be the length of the longest increasing subsequence ending at index i. For each i, scan all j < i where nums[j] < nums[i] and take max(dp[j]) + 1. Correct and standard, but quadratic in runtime.

  3. Patience sorting with binary searchWrite this one

    time O(n log n) · space O(n)

    Maintain an array `tails` where tails[len] stores the smallest ending value among all increasing subsequences of length len + 1 seen so far. For each number, binary search for its insertion point: either replace the first tail >= num, or append if greater than all.

Where people lose marks · 3
  • Confusing strictly increasing with non-decreasing. When nums[i] equals a tail element, it cannot extend the subsequence; binary search must look for lower_bound (first >=) rather than upper_bound.
  • Assuming the `tails` array itself contains the actual longest increasing subsequence. It stores minimal tail values across different valid subsequences, not a single sequence.
  • Seeding the DP array with 0 instead of 1. A single element by itself always forms a valid increasing subsequence of length 1.

The theory behind it

Dynamic Programming — the ground this problem stands on. All Dynamic Programming problems

What Dynamic Programming is

Dynamic programming is a method for solving a complex problem by breaking it into overlapping subproblems, solving each subproblem only once, and remembering the answers in a lookup table. Instead of recalculating identical questions over and over, future steps look up previous answers directly. By assembling these saved pieces from the bottom up or storing them during recursion, a task that would take billions of steps finishes in a fraction of a second.

When to reach for it

Reach for dynamic programming when questions ask for the maximum profit, minimum cost, total number of distinct ways to achieve a goal, or whether a target can be formed. Signals include overlapping choices where making a choice now affects what choices remain later, but greedy picking fails to find the true global optimum. If drawing a recursive decision tree reveals the same subproblem states repeating across branches, dynamic programming is needed.

How the pattern works

Identify the state variables that uniquely describe a subproblem, such as an array index and remaining capacity. Write the base cases first, representing states whose answers are known without calculation. Next, write the recurrence relation that expresses the current state using previously solved states, taking the minimum, maximum, or sum among your options. Build the solution either top-down by caching recursive returns in a memo table, or bottom-up by filling an array in topological dependency order. When each state depends only on the previous row, compress storage down to a single array.

More Dynamic Programming problems

Track in your role's order

Pick your target role and all 370 problems resequence to what that interview actually asks.

Start free

Problem set and role mapping as of .