Longest Increasing Subsequence
Find the length of the longest strictly increasing subsequence in O(n log n). Keep tails, where tails[k] is the smallest possible tail of an increasing subsequence of length k+1. For each number, binary-search the first tail ≥ it and replace it (or append if none).
Traced input: nums = [10, 9, 2, 5, 3, 7, 101, 18] → 4. Original problem: neetcode.io/problems/longest-increasing-subsequence
Complexity
BestO(n log n)
AverageO(n log n)
WorstO(n log n)
SpaceO(n)
One binary search per element. The O(n²) DP is the simpler alternative.
Key idea
- A smaller tail is always better: it leaves more room for future numbers.
tailsstays sorted, so binary search applies.- Replacing doesn't change the length; appending extends the best length by one.
tailsisn't an actual subsequence, but its length is the answer.
Common mistakes
- Using
>instead of>=in the search allows equal values (non-strict LIS). - Returning
tailsas the subsequence; it isn't one.
Solution
Java
int lengthOfLIS(int[] nums) {
int[] tails = new int[nums.length];
int size = 0;
for (int i = 0; i < nums.length; i++) {
int x = nums[i];
int lo = 0, hi = size;
while (lo < hi) {
int mid = (lo + hi) / 2;
if (tails[mid] < x) lo = mid + 1;
else hi = mid;
}
tails[lo] = x;
if (lo == size) size++;
}
return size;
}Python
def lengthOfLIS(nums: List[int]) -> int:
tails = []
for x in nums:
i = bisect.bisect_left(tails, x)
if i == len(tails): tails.append(x)
else: tails[i] = x
return len(tails)C++
int lengthOfLIS(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();
}Edge cases
Each one has its own trace in the interactive view.
| Case | Input | Answer |
|---|---|---|
| All equal Strictly increasing, so equal values don't extend. | nums = [7, 7, 7, 7] | 1 |
| Strictly decreasing Each number replaces the only tail. | nums = [5, 4, 3, 2] | 1 |
| Already sorted Every number appends. | nums = [1, 2, 3, 4] | 4 |
| Single element Length 1. | nums = [0] | 1 |