DSA Notes
Master Longest Increasing Subsequence (LIS) completely — the O(n²) DP solution, the O(n log n) patience sorting algorithm, reconstructing the actual LIS, variants including longest non-decreasing subsequence and bitonic subsequence, and applications in scheduling and sequence analysis.
Definition
The Longest Increasing Subsequence (LIS) of an array is the longest subsequence where every element is strictly greater than the previous element.
Solution 2 — O(n log n) with Patience Sorting
The key insight: maintain a tails array where tails[i] = smallest tail element of all increasing subsequences of length i+1.
Step-by-step trace for [3, 1, 4, 1, 5, 9, 2, 6]:
| Start | tails = [] |
| num=3: tails=[] | append → tails=[3] |
| num=1: bisect_left([3],1)=0 | replace → tails=[1] |
| num=4: bisect_left([1],4)=1 | append → tails=[1,4] |
| num=1: bisect_left([1,4],1)=0 | replace → tails=[1,4] |
| num=5: bisect_left([1,4],5)=2 | append → tails=[1,4,5] |
| num=9: bisect_left([1,4,5],9)=3 | append → tails=[1,4,5,9] |
| num=2: bisect_left([1,4,5,9],2)=1 | replace → tails=[1,2,5,9] |
| num=6: bisect_left([1,2,5,9],6)=3 | replace → tails=[1,2,5,6] |
| len(tails) = 4 | LIS length = 4 ✓ |
| Note | tails is NOT the actual LIS. It's a clever tool for counting. |
Why does this work?
tailsis always sorted (invariant)tails[i]is the optimal (smallest) ending for IS of length i+1- Binary search finds where the current number fits or improves
- Replacing a larger tail with a smaller one maintains the invariant and allows future elements to extend longer sequences
Reconstruct the Actual LIS
LIS Variants
Non-Decreasing (≥ instead of >)
Longest Decreasing Subsequence
Longest Bitonic Subsequence
A bitonic subsequence first increases then decreases.
Number of LIS
Classic Interview Problem — Russian Dolls / Box Stacking
LIS on pairs (sort by one dimension, find LIS on the other):
Complexity Summary
| Approach | Time | Space | Notes |
|---|---|---|---|
| O(n²) DP | O(n²) | O(n) | Simple, good for n ≤ 1000 |
| O(n log n) patience | O(n log n) | O(n) | For n ≤ 10^5 or more |
| With reconstruction | O(n log n) | O(n) | Needs parent array |
| Bitonic | O(n²) | O(n) | Run LIS/LDS for each index |
Summary
LIS is one of the most important DP problems:
- O(n²) solution:
dp[i] = max(dp[j]+1 for j<i where nums[j]<nums[i]) - O(n log n) solution: Maintain sorted tails array, binary search for position
- Key insight for O(n log n): Replacing a larger tail with a smaller one is always beneficial — it gives future elements more chances to extend the subsequence
Common interview appearance: "Scheduling" problems that reduce to LIS, Russian dolls, envelope nesting, and any problem requiring "select a chain where each element satisfies a condition relative to the previous one."
*Next Lesson: Matrix Chain Multiplication*
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Longest Increasing Subsequence — O(n log n) with Patience Sorting.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this Data Structures & Algorithms topic.
Search Terms
data-structures-algorithms, data structures & algorithms, data, structures, algorithms, dynamic, programming, longest
Related Data Structures & Algorithms Topics