Longest Increasing Subsequence DSA Solution - Study Chapter | QuizMaker

Longest Increasing Subsequence explained with O(n^2) DP, optimized binary search DP, dry run, edge cases, complexity, and Python, C++, Java code.

Read
12m
Type
Chapter
Access
Free

Course

DSA Course: Interview Patterns and Problem Solving

Topic

Module 8: Dynamic Programming

Learning Outcome

After this lesson, you should be able to use tails to preserve future choices while computing LIS length in O(n log n).

Problem Statement

Given an integer array, return the length of the longest strictly increasing subsequence.

InputOutputWhy
nums = [10,9,2,5,3,7,101,18]4One longest increasing subsequence is [2,3,7,101].

Brute Force Approach

For each index, compare with every previous index and build dp[i]. This is valid but costs O(n^2).

Optimized Approach

Maintain tails[len], the smallest possible ending value for an increasing subsequence of that length. Use binary search to replace the first tail >= current number.

Exact Pseudocode

tails = empty list
for x in nums:
  i = lower_bound(tails, x)
  if i equals length of tails:
    append x
  else:
    tails[i] = x
return length of tails

Reference Code

import bisect

class Solution:
    def lengthOfLIS(self, nums):
        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)
class Solution {
public:
    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();
    }
};
class Solution {
    public int lengthOfLIS(int[] nums) {
        int[] tails = new int[nums.length];
        int size = 0;

        for (int x : nums) {
            int i = Arrays.binarySearch(tails, 0, size, x);
            if (i < 0) i = -(i + 1);
            tails[i] = x;
            if (i == size) size++;
        }

        return size;
    }
}

Sample Dry Run

StepStateResult
10tails = [10]length 1
9replace 10tails = [9]
2,5,3,7tails becomes [2,3,7]length 3
101 then 18[2,3,7,101] then [2,3,7,18]answer = 4

Complexity

MeasureValueReason
TimeO(n log n)Each number performs one binary search over tails.
SpaceO(n)The tails array can grow up to n.

Edge Cases

Interview Checklist

FAQs

Why replace a tail with a smaller value?

A smaller tail gives future numbers more chance to extend the subsequence.

Is tails the final subsequence?

Not necessarily. It is a helper array for lengths.

What is the core pattern?

Binary-search DP with greedy tails.

Tags

Open on QuizMaker