dynamic programming
algorithms
subsequence
computer science
LIS

Longest increasing subsequence

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

Introduction

The Longest Increasing Subsequence (LIS) problem is a fundamental combinatorial problem in computer science and mathematics. Given a sequence of numbers, the task is to identify the longest subsequence in which the elements are in increasing order. This problem has applications in various fields such as bioinformatics, pattern recognition, and data compression.

Definition

Formally, given a sequence of integers S=s1,s2,,snS = {s_1, s_2, \ldots, s_n}, the objective is to find a subsequence S=si1,si2,,sikS' = {s'_{i_1}, s'_{i_2}, \ldots, s'_{i_k}} such that: • si1<si2<<siks'_{i_1} < s'_{i_2} < \ldots < s'_{i_k} • The length of SS' is the maximum among all possible increasing subsequences of SS.

Example

Consider the sequence S=[10,22,9,33,21,50,41,60,80]S = [10, 22, 9, 33, 21, 50, 41, 60, 80]. One possible longest increasing subsequence is [10,22,33,50,60,80][10, 22, 33, 50, 60, 80], which has a length of 6.

Algorithms

Dynamic Programming Approach

The most straightforward approach to solving the LIS problem is through dynamic programming. The idea is to construct an array `dp[]` where `dp[i]` represents the length of the longest increasing subsequence ending at index `i`.

Steps:

  1. Initialize `dp[]` with all entries as 1, since every element is an increasing subsequence of length 1 by itself.
  2. For each element at index `i`, check all previous elements `j` (where 0j<i0 \le j < i) and update `dp[i]` if a longer increasing subsequence ending at `i` is found: dp[i]=max(dp[i],dp[j]+1) if S[i]>S[j]dp[i] = \max(dp[i], dp[j] + 1) \text{ if } S[i] > S[j]
  3. The result is the maximum value in `dp[]`.

Complexity: The time complexity of this approach is O(n2)O(n^2) where nn is the length of the sequence.

A more efficient solution can be developed using a combination of patience sorting and binary search. This method reduces the time complexity to O(nlogn)O(n \log n).

Steps:

  1. Initialize an empty list `tail`.
  2. Iterate over each element in the sequence: • Use binary search (in conjunction with the `bisect` module in Python) to find the position where the current element can replace a larger element in `tail`. • If the element is larger than all elements in `tail`, append it. • Otherwise, replace the found position in `tail` with the current element.
  3. The length of `tail` at the end of iteration is the length of the LIS.

Why it Works: The `tail` array maintains potential candidates for the LIS, often hinting at where the current subsequence could continue or evolve.

Example Implementation

Here is an example of the patience sorting algorithm with binary search in Python:


Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

All Rights Reserved.