Longest Increasing Subsequence
Learn the LIS algorithm with dynamic programming. Compare O(n²) and O(n log n) solutions using patience sorting.
Visualize LIS dynamic programming solution step by step.
Home → CS Student Hub → Longest Increasing Subsequence
The longest increasing subsequence (LIS) problem asks: given a sequence of numbers, find the length of the longest subsequence where elements are in strictly increasing order. This is a classic LIS dynamic programming problem with both O(n²) and O(n log n) solutions.
📌 Example: [10, 9, 2, 5, 3, 7, 101, 18]
LIS: [2, 5, 7, 101] → Length = 4 (other answers of length 4 exist, such as [2, 3, 7, 101])
Patience sorting LIS achieves O(n log n) time complexity.
LIS Dynamic Programming Visualizer
Enter a sequence to find the longest increasing subsequence and visualize the DP solution.
Unlock Your Potential
Turn your highest ambitions into everyday reality. You set the standard and aim for the goal; when you're ready for what comes next, we help you cross the finish line.
Own Your Future →LIS Example: [10, 9, 2, 5, 3, 7, 101, 18]
Walk through a complete LIS example step by step.
Step 1 (O(n²) DP): dp[i] = length of LIS ending at position i
Step 2 (Recurrence): dp[i] = max(dp[j] + 1) for all j < i where nums[j] < nums[i] Step 3: After computing all dp[i], take the maximum value Step 4 (Patience Sorting): Place each number on the leftmost pile where top card ≥ current numberAnswer: LIS length = 4 (for example [2, 5, 7, 101]; [2, 3, 7, 101], [2, 5, 7, 18] and [2, 3, 7, 18] are equally long)
LIS Algorithm Explained
Understanding the longest increasing subsequence algorithm and both solution approaches.
O(n²) Dynamic Programming
Create a dp array where dp[i] = length of LIS ending at index i. For each i, check all previous j where nums[j] < nums[i] and take the maximum dp[j] + 1. Time complexity O(n²).
O(n log n) Patience Sorting
Maintain piles where each new number is placed on the leftmost pile with top card ≥ current number. The number of piles equals the LIS length. Use binary search for O(n log n) complexity.
Backtrack to Find LIS
After computing dp values, trace backwards to reconstruct the actual longest increasing subsequence, not just its length.
How to Print the Actual LIS (Not Just the Length)
The DP table gives the length. To print the subsequence itself, keep a second array prev[i]: the index of the element just before nums[i] in the best subsequence ending at i. Then start at the largest dp value and follow prev backwards.
nums = [10, 9, 2, 5, 3, 7, 101, 18]
| i | nums[i] | dp[i] | prev[i] |
|---|---|---|---|
| 0 | 10 | 1 | – |
| 1 | 9 | 1 | – |
| 2 | 2 | 1 | – |
| 3 | 5 | 2 | 2 |
| 4 | 3 | 2 | 2 |
| 5 | 7 | 3 | 3 |
| 6 | 101 | 4 | 5 |
| 7 | 18 | 4 | 5 |
Green rows are the path we follow back. "–" means there is no previous element.
Step 1: The largest dp value is 4, first reached at index 6 (value 101).
Step 2: prev[6] = 5, so the element before 101 is nums[5] = 7.
Step 3: prev[5] = 3, so before 7 comes nums[3] = 5.
Step 4: prev[3] = 2, so before 5 comes nums[2] = 2.
Step 5: prev[2] = –, so we stop. Reading what we collected in reverse gives [2, 5, 7, 101].
Other answers of length 4 exist: [2, 3, 7, 101], [2, 5, 7, 18] and [2, 3, 7, 18]. Which one you get depends on tie-breaking. The visualizer above keeps the first best predecessor, so it prints [2, 5, 7, 101].
LIS Code: Python and C++
The same two solutions in code: the O(n²) DP that rebuilds the subsequence, and the O(n log n) patience sorting version that returns the length.
Python
from bisect import bisect_left
def lis_dp(nums):
"""O(n^2) DP. Returns the actual longest increasing subsequence."""
if not nums:
return []
n = len(nums)
dp = [1] * n # dp[i] = length of the LIS ending at i
prev = [-1] * n # prev[i] = index of the element before i in that LIS
for i in range(n):
for j in range(i):
if nums[j] < nums[i] and dp[j] + 1 > dp[i]:
dp[i] = dp[j] + 1
prev[i] = j
end = max(range(n), key=lambda i: dp[i]) # where the best LIS ends
seq = []
while end != -1:
seq.append(nums[end])
end = prev[end]
return seq[::-1]
def lis_length(nums):
"""O(n log n) patience sorting. Returns the length only."""
tails = [] # tails[k] = smallest tail of any increasing run of length k+1
for x in nums:
k = bisect_left(tails, x)
if k == len(tails):
tails.append(x)
else:
tails[k] = x
return len(tails)
print(lis_dp([10, 9, 2, 5, 3, 7, 101, 18])) # [2, 5, 7, 101]
print(lis_length([10, 9, 2, 5, 3, 7, 101, 18])) # 4
C++
#include <bits/stdc++.h>
using namespace std;
// O(n^2) DP that also rebuilds the actual subsequence
vector<int> lisDp(const vector<int>& nums) {
int n = nums.size();
if (n == 0) return {};
vector<int> dp(n, 1), prev(n, -1);
for (int i = 0; i < n; i++)
for (int j = 0; j < i; j++)
if (nums[j] < nums[i] && dp[j] + 1 > dp[i]) {
dp[i] = dp[j] + 1;
prev[i] = j;
}
int end = max_element(dp.begin(), dp.end()) - dp.begin();
vector<int> seq;
for (; end != -1; end = prev[end]) seq.push_back(nums[end]);
reverse(seq.begin(), seq.end());
return seq;
}
// O(n log n): length only (patience sorting with binary search)
int lisLength(const vector<int>& nums) {
vector<int> tails;
for (int x : nums) {
auto it = lower_bound(tails.begin(), tails.end(), x);
if (it == tails.end()) tails.push_back(x);
else *it = x;
}
return tails.size();
}
int main() {
vector<int> nums = {10, 9, 2, 5, 3, 7, 101, 18};
for (int x : lisDp(nums)) cout << x << " "; // 2 5 7 101
cout << "\nlength = " << lisLength(nums) << "\n"; // 4
}
These find a strictly increasing subsequence. For a non-decreasing one, use bisect_right in Python or upper_bound in C++ instead.
Free LIS Cheat Sheet
Printable PDF with recurrence relation, O(n²) DP algorithm, O(n log n) patience sorting, complexity comparison, and practice problems.
📥 Download LIS Cheat Sheet (PDF)No email required. Instant download.
Frequently Asked Questions
Common questions about the longest increasing subsequence and LIS algorithm.
What is the longest increasing subsequence (LIS) problem?
The longest increasing subsequence problem asks: given a sequence of numbers, find the length of the longest subsequence where elements are in strictly increasing order. The subsequence doesn't need to be contiguous.
What is the time complexity of LIS?
There are two common solutions: O(n²) using dynamic programming, and O(n log n) using patience sorting with binary search.
How does patience sorting work for LIS?
Patience sorting LIS maintains piles where each new number is placed on the leftmost pile with top card ≥ current number. The number of piles at the end equals the LIS length. This method runs in O(n log n).
What's the recurrence relation for LIS DP?
The LIS dynamic programming recurrence is: dp[i] = max(dp[j] + 1) for all j < i where nums[j] < nums[i], with dp[i] initialized to 1.
Is this LIS visualizer free?
Yes! This LIS algorithm visualizer is completely free. No signup needed. Just open the tool and start learning.
How do I print the actual LIS, not just its length?
Keep a prev array next to dp. When dp[i] improves because of index j, set prev[i] = j. At the end, start at the index with the largest dp value and follow prev backwards, then reverse what you collected. The section above walks through this for [10, 9, 2, 5, 3, 7, 101, 18].
How many longest increasing subsequences are there?
Keep a count array cnt[i], the number of longest subsequences ending at i. When dp[j] + 1 is greater than dp[i], set dp[i] = dp[j] + 1 and cnt[i] = cnt[j]. When it is equal, add: cnt[i] += cnt[j]. The answer is the sum of cnt[i] over all i where dp[i] equals the maximum. For [10, 9, 2, 5, 3, 7, 101, 18] there are 4.
Additional Resources
Explore more algorithm visualizers and study guides.
Still Stuck on LIS?
Whether it’s the LIS algorithm, DP recurrence, or patience sorting — submit your question and we’ll send you a step-by-step solution.
Submit Your Question — Get a Step-by-Step Solution
One of our CS experts will review your problem and send you a detailed, step-by-step explanation within 24-48 hours. Free. No strings attached.
📋 Before you submit:
- Be specific about the sequence you’re trying to solve
- Share where exactly you’re getting stuck (DP table? recurrence?)
- Include any steps you’ve already completed
Fill out the form below
🔒 Your email is safe with us. We’ll never share your information. Questions may be anonymized and added to our FAQ to help other students.
⚠️ Important Disclaimer
This form is for educational assistance only. We aim to respond within 24-48 hours, but response times may vary based on volume.
While we strive to provide accurate, step-by-step explanations, we cannot guarantee the correctness of every solution. Our guidance is meant to help you learn — not to replace your own work or your professor’s instruction.
For urgent exam questions, please consult your professor or teaching assistant. We do not provide last-minute solutions.
Get More DP Resources First
Be the first to know when new visualizers, guides, and calculators are released. No spam, just helpful content.
We respect your privacy. Unsubscribe anytime.
Free tools and study guides for computer science students.
