Learn through the super-clean Baeldung Pro experience:
>> Membership and Baeldung Pro.
No ads, dark-mode and 6 months free of IntelliJ Idea Ultimate to start with.
Last updated: March 18, 2024
In this tutorial, we’re going to walk through the Longest Increasing Subsequence (LIS) problem.
Given an array of unsorted elements, the idea is to find the length of the longest subsequence whose elements are in ascending order (from lowest to highest).
The elements in the subsequence do not necessarily have to appear in consecutive positions in the initial array, and the solution of LIS is not always unique.
For elements {-3, 10, 5, 12, 15} we identify the following increasing subsequences.
As we can see from the list, the longest increasing subsequence is {-3, 5, 12, 15} with length 4. However, it’s not the only solution, as {-3, 10, 12, 15} is also the longest increasing subsequence with equal length.
The naive implementation of LIS is to first consider all possible subsequences of the given array. Then, we check every subsequence that is increasing and store the length of it. After doing this process, we can return the length of the longest one that we found:
algorithm NaiveLIS(array):
// INPUT
// array = The input array
// OUTPUT
// LIS = The longest increasing subsequence
while true:
Sub <- all possible subsequences of array
maxLis <- 1
for S in Sub:
if isIncreasing(S):
len <- length(S)
maxLis <- max(maxLis, len)
return maxLis
The complexity of this approach is O(2^n) because an array of size n contains 2^n subsets. For example [1,2,3] contains subsets {}, {1}, {2}, {3}, {1,2}, {1,3}, {2,3}, {1,2,3}.
We can improve our performance with a dynamic programming approach. Recall that dynamic programming is a technique that involves breaking down a problem into multiple smaller subproblems and using those solutions to construct our larger one.
Specifically in this case, we can use tabulation:
The intuition behind this algorithm is that we can find all the increasing subsequences for a number at index i by looking at all the previous numbers until i-1, eventually reaching the longest one:
algorithm DPLIS(array):
// INPUT
// array = The input array of size n
// OUTPUT
// LIS = The longest increasing subsequence
n <- size of array
Lis <- array of 1s of size n
for i <- 2 to n:
for j <- 1 to i - 1:
if array[i] > array[j] and Lis[i] <= Lis[j]:
Lis[i] <- Lis[j] + 1
return max(Lis[0], Lis[1], ..., Lis[n])
The complexity of this is O(n^2) because we traverse the array once in the outer loop, yielding a complexity of O(n), and then for every element i, we make a linear search of all elements j from 1 up to i.
In this tutorial, we presented the Longest Increasing Subsequence problem.
We also had a look at a naive implementation and one using dynamic programming.