InterviewPrepKit

Home / Coding / 1-D Dynamic Programming

Longest Increasing Subsequence

medium Original ↗
Solving tips
  • Baseline O(n^2) DP: dp[i] = longest increasing subsequence ending at i = 1 + max(dp[j]) over j<i with nums[j]<nums[i]; answer is max(dp), not dp[n-1].
  • For O(n log n) use patience sorting: keep tails[k] = smallest tail of an increasing subsequence of length k+1; bisect and overwrite or append.
  • Use bisect_left for strictly increasing (equal values overwrite); bisect_right would solve the non-strict variant.
  • Remember tails is not an actual subsequence - only its final length is the answer.

Problem

Given an integer array nums, return the length of the longest strictly increasing subsequence. A subsequence keeps the original left-to-right order but may drop any elements; it does not have to be contiguous.

Examples

  • nums = [10,9,2,5,3,7,101,18]4 — one longest increasing subsequence is [2,3,7,101] (also [2,3,7,18]).
  • nums = [0,1,0,3,2,3]4 — e.g. [0,1,2,3].
  • nums = [7,7,7,7]1 — “strictly” increasing, so equal elements don’t extend anything.

Constraints

  • 1 <= nums.length <= 2500
  • -10⁴ <= nums[i] <= 10⁴
  • A follow-up asks for an O(n log n) solution.

Think about it first

Hint 1 Define dp[i] = length of the longest increasing subsequence that ends exactly at index i. What smaller answers does it build on? Look at every earlier index j with nums[j] < nums[i].
Hint 2 dp[i] = 1 + max(dp[j]) over all j < i with nums[j] < nums[i], or 1 if there's no such j. The answer is max(dp), not dp[n-1]. That's O(n²).
Hint 3 For O(n log n): keep a list tails where tails[k] is the smallest possible tail value of an increasing subsequence of length k+1. For each number, binary-search the first tail that is >= it and overwrite it (or append). The length of tails is the answer. This is patience sorting.
Your workspace Not runnable by design — this is your interview scratchpad. Saved on this device.