Longest Increasing Subsequence (LIS)

Last Updated : 12 Apr, 2026

Given an array arr[] of size n, find the length of the Longest Increasing Subsequence (LIS) i.e., the longest possible subsequence in which the elements of the subsequence are sorted in strictly increasing order.

Examples:

Input: arr[] = [3, 10, 2, 1, 20]
Output: 3
Explanation: The longest increasing subsequence is 3, 10, 20

Input: arr[] = [30, 20, 10]
Output:1
Explanation: The longest increasing subsequences are [30], [20] and [10]

Input: arr[] = [2, 2, 2]
Output: 1
Explanation: We consider only strictly increasing subsequences, therefore the longest increasing subsequence is [2].

Input: arr[] = [3, 4, 5, 1, 2, 3, 4]
Output: 4
Explanation: The longest strictly increasing subsequence is [1, 2, 3, 4], which gives a maximum length of 4. (Note: [3, 4, 5] is also an increasing subsequence, but its length is only 3).

Try It Yourself
redirect icon

[Naive Approach] Using Recursion - Exponential Time and Linear Space

The idea to do traverse the input array from left to right and find length of the Longest Increasing Subsequence (LIS) ending with every element arr[i]. Let the length found for arr[i] be L[i]. At the end we return maximum of all L[i] values. Now to compute L[i], we use recursion, we consider all smaller elements on left of arr[i], recursively compute LIS value for all the smaller elements on left, take the maximum of all and add 1 to it. If there is no smaller element on left of an element, we return 1.

Let L(i) be the length of the LIS ending at index i such that arr[i] is the last element of the LIS. Then, L(i) can be recursively written as: 

  • L(i) = 1 + max(L(prev) ) where 0 < prev < i and arr[prev] < arr[i]; or
  • L(i) = 1, if no such prev exists.

Formally, the length of LIS ending at index i, is 1 greater than the maximum of lengths of all LIS ending at some index prev such that arr[prev] < arr[i] where prev < i.

After we fill the L array, we find LIS as maximum of all in L[]

Overall LIS = max(L[i]) where 0 <= i < n

We can see that the above recurrence relation follows the optimal substructure property. Follow the below illustration to see overlapping subproblems.

Consider arr[] = [3, 10, 2, 11]

L(i): Denotes LIS of subarray ending at position 'i'

Recursion Tree


C++
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

// Returns LIS of subarray ending with index i.
int lisEndingAtIdx(vector<int>& arr, int idx) {
    
    // Base case
    if (idx == 0)
        return 1;

    // Consider all elements on the left of i,
    // recursively compute LISs ending with 
    // them and consider the largest
    int mx = 1;
    for (int prev = 0; prev < idx; prev++)
        if (arr[prev] < arr[idx])
            mx = max(mx, lisEndingAtIdx(arr, prev) + 1);
    return mx;
}

int lis(vector<int>& arr) {
    int n = arr.size();
    int res = 1;
    for (int i = 1; i < n; i++)
        res = max(res, lisEndingAtIdx(arr, i));
    return res;
}

int main() {
    vector<int> arr = {3, 10, 2, 1, 20};
    cout << lis(arr);
    return 0;
}
Java
class GfG {
    static int lisEndingAtIdx(int[] arr, int idx) {
      
        // Base case
        if (idx == 0)
            return 1;

        // Consider all elements on the left of i,
        // recursively compute LISs ending with 
        // them and consider the largest
        int mx = 1;
        for (int prev = 0; prev < idx; prev++)
            if (arr[prev] < arr[idx])
                mx = Math.max(mx, lisEndingAtIdx(arr, prev) + 1);
        return mx;
    }

    static int lis(int[] arr) {
        int n = arr.length;
        int res = 1;
        for (int idx = 1; idx < n; idx++)
            res = Math.max(res, lisEndingAtIdx(arr, idx));
        return res;
    }

    public static void main(String[] args) {
        int[] arr = { 3, 10, 2, 1, 20 };
        System.out.println(lis(arr));
    }
}
Python
def lisEndingAtIdx(arr, idx):
  
    # Base case
    if idx == 0:
        return 1

    # Consider all elements on the left of i,
    # recursively compute LISs ending with 
    # them and consider the largest
    mx = 1
    for prev in range(idx):
        if arr[prev] < arr[idx]:
            mx = max(mx, lisEndingAtIdx(arr, prev) + 1)
    return mx

def lis(arr):
    n = len(arr)
    res = 1
    for idx in range(1, n):
        res = max(res, lisEndingAtIdx(arr, idx))
    return res

if __name__ == "__main__":
    arr = [3, 10, 2, 1, 20]
    print(lis(arr))
C#
using System;

class GfG {
    static int lisEndingAtIdx(int[] arr, int idx) {
        // Base case
        if (idx == 0)
            return 1;

        // Consider all elements on the left of i,
        // recursively compute LISs ending with 
        // them and consider the largest
        int mx = 1;
        for (int prev = 0; prev < idx; prev++)
            if (arr[prev] < arr[idx])
                mx = Math.Max(mx, lisEndingAtIdx(arr, prev) + 1);
        return mx;
    }

    static int lis(int[] arr) {
        int n = arr.Length;
        int res = 1;
        for (int idx = 1; idx < n; idx++)
            res = Math.Max(res, lisEndingAtIdx(arr, idx));
        return res;
    }

    static void Main(string[] args) {
        int[] arr = { 3, 10, 2, 1, 20 };
        Console.WriteLine(lis(arr));
    }
}
JavaScript
function lisEndingAtIdx(arr, idx) {

    // Base case
    if (idx === 0)
        return 1;

    // Consider all elements on the left of i,
    // recursively compute LISs ending with
    // them and consider the largest
    let mx = 1;
    for (let prev = 0; prev < idx; prev++) {
        if (arr[prev] < arr[idx]) {
            mx = Math.max(mx,
                          lisEndingAtIdx(arr, prev) + 1);
        }
    }
    return mx;
}

function lis(arr) {
    let n = arr.length;
    let res = 1;
    for (let idx = 1; idx < n; idx++) {
        res = Math.max(res, lisEndingAtIdx(arr, idx));
    }
    return res;
}

let arr = [ 3, 10, 2, 1, 20];
console.log(lis(arr));

Output
4

[Better Approach - 1] Using Memoization - O(n^2) Time and O(n) Space

In the recursive solution, each index tries to compute the LIS ending at that position by checking all smaller indices. However, many of these smaller-index calls overlap.
For example, while solving LIS at idx = 7, you may again need the LIS at indices 3, 5, or 6 - and these same indices might also be needed when solving LIS for other positions. This leads to repeated computation of the same subproblems.
To avoid this, we use a dp array where dp[idx] stores the LIS length ending at index idx, and reuse it whenever needed later.
This memoization ensures that each index’s LIS is computed only once, reducing the overall time complexity from exponential to quadratic.

C++
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int lisEndingAtIdx(vector<int>& arr, int idx, vector<int>& dp) {
      
    // Base case
    if (idx == 0)
        return 1;

    // Check if the result is already computed
    if (dp[idx] != -1)
        return dp[idx];

    // Consider all elements on left of i,
    // recursively compute LIS ending with 
    // them and consider the largest
    int maxLen = 1;
    for (int prev = 0; prev < idx; prev++)
        if (arr[prev] < arr[idx])
            maxLen = max(maxLen, lisEndingAtIdx(arr, prev, dp) + 1);

    // Store the result in the memo array
    dp[idx] = maxLen;
    return dp[idx];
}

int lis(vector<int>& arr) {
    int n = arr.size();
  
    // filling dp array with invalid value
    vector<int> dp(n, -1);
  
    int res = 1;
    for (int idx = 1; idx < n; idx++)
        res = max(res, lisEndingAtIdx(arr, idx, dp));
        
    return res;
}

int main() {
    vector<int> arr = {3, 10, 2, 1, 20};
    cout << lis(arr);
    return 0;
}
Java
import java.util.Arrays;

class GFG {
    static int lisEndingAtIdx(int[] arr, int idx, int[] dp) {
      
        // Base case
        if (idx == 0)
            return 1;

        // Check if the result is already computed
        if (dp[idx] != -1)
            return dp[idx];

        // Consider all elements on left of i,
        // recursively compute LIS ending with 
        // them and consider the largest
        int maxLen = 1;
        for (int prev = 0; prev < idx; prev++)
            if (arr[prev] < arr[idx])
                maxLen = Math.max(maxLen, lisEndingAtIdx(arr, prev, dp) + 1);

        // Store the result in the memo array
        dp[idx] = maxLen;
        return dp[idx];
    }

    static int lis(int[] arr) {
        int n = arr.length;
      
        int[] dp = new int[n];
        
        // filling dp array with invalid value
        Arrays.fill(dp, -1);
      
        int res = 1;
        for (int idx = 1; idx < n; idx++)
            res = Math.max(res, lisEndingAtIdx(arr, idx, dp));
        return res;
    }

    public static void main(String[] args) {
        int[] arr = {3, 10, 2, 1, 20};
        System.out.println(lis(arr));
    }
}
Python
def lisEndingAtIdx(arr, idx, dp):
      
    # Base case
    if idx == 0:
        return 1

    # Check if the result is already computed
    if dp[idx] != -1:
        return dp[idx]

    # Consider all elements on left of i,
    # recursively compute LIS ending with 
    # them and consider the largest
    maxLen = 1
    for prev in range(idx):
        if arr[prev] < arr[idx]:
            maxLen = max(maxLen, lisEndingAtIdx(arr, prev, dp) + 1)

    # Store the result in the memo array
    dp[idx] = maxLen
    return dp[idx]

def lis(arr):
    n = len(arr)
  
    
    # filling dp array with invalid value
    dp = [-1] * n
  
    res = 1
    for idx in range(1, n):
        res = max(res, lisEndingAtIdx(arr, idx, dp))
    return res


if __name__ == "__main__":
    arr = [3, 10, 2, 1, 20]
    print(lis(arr))
C#
using System;

class GfG {

    static int lisEndingAtIdx(int[] arr, int idx, int[] dp) {
      
        // Base case
        if (idx == 0)
            return 1;

        // Check if the result is already computed
        if (dp[idx] != -1)
            return dp[idx];

        // Consider all elements on left of i,
        // recursively compute LIS ending with 
        // them and consider the largest
        int maxLen = 1;
        for (int prev = 0; prev < idx; prev++)
            if (arr[prev] < arr[idx])
                maxLen = Math.Max(maxLen, lisEndingAtIdx(arr, prev, dp) + 1);

        // Store the result in the memo array
        dp[idx] = maxLen;
        return dp[idx];
    }

    static int lis(int[] arr) {
        int n = arr.Length;
      
        int[] dp = new int[n];
        
        // filling dp array with invalid value
        for (int i = 0; i < n; i++) dp[i] = -1;
      
        int res = 1;
        for (int idx = 1; idx < n; idx++)
            res = Math.Max(res, lisEndingAtIdx(arr, idx, dp));
        return res;
    }

    public static void Main() {
        int[] arr = {3, 10, 2, 1, 20};
        Console.WriteLine(lis(arr));
    }
}
JavaScript
function lisEndingAtIdx(arr, idx, dp) {
      
    // Base case
    if (idx === 0)
        return 1;

    // Check if the result is already computed
    if (dp[idx] !== -1)
        return dp[idx];

    // Consider all elements on left of i,
    // recursively compute LIS ending with 
    // them and consider the largest
    let maxLen = 1;
    for (let prev = 0; prev < idx; prev++)
        if (arr[prev] < arr[idx])
            maxLen = Math.max(maxLen, lisEndingAtIdx(arr, prev, dp) + 1);

    // Store the result in the memo array
    dp[idx] = maxLen;
    return dp[idx];
}

function lis(arr) {
    let n = arr.length;
    
    // filling dp array with invalid value
    let dp = Array(n).fill(-1);
  
    let res = 1;
    for (let idx = 1; idx < n; idx++)
        res = Math.max(res, lisEndingAtIdx(arr, idx, dp));
    return res;
}

// Driver code
let arr = [3, 10, 2, 1, 20];
console.log(lis(arr));

Output
4

[Better Approach - 2] Using DP (Bottom Up Tabulation) - O(n^2) Time and O(n) Space

The idea is to maintain a 1D array lis[], where lis[i] stores the length of the longest increasing subsequence that ends at index i. Initially, each element in lis[] is set to 1, as the smallest possible subsequence for any element is the element itself.

The algorithm then iterates over each element of the array. For each element arr[i], it checks all previous elements arr[0] to arr[i-1]. If arr[i] is greater than arr[prev] (ensuring the subsequence is increasing), it updates lis[i] to the maximum of its current value or lis[prev] + 1, indicating that we can extend the subsequence ending at arr[prev] by including arr[i].

Finally, the length of the longest increasing subsequence is the maximum value in the lis[] array.

In this approach, we build the solution from smaller subproblems to larger ones. We start by assuming that the LIS ending at each index is 1 (every single element is an LIS of length 1). Then, for each index i, we look at all previous indices prev < i. If arr[prev] < arr[i], it means the subsequence ending at prev can be extended by arr[i]. So we update lis[i] using the best LIS found so far for all valid previous positions.

By the time we reach the end of the array, lis[i] already contains the correct LIS ending at i, because all smaller subproblems (earlier indices) have been computed. Finally, the overall LIS is the maximum value in the lis array.

C++
#include <vector>
#include <iostream>
using namespace std;

int lis(vector<int>& arr) {
    int n = arr.size();
    vector<int> lis(n, 1);

    // Compute optimized LIS values in
    // bottom-up manner
    for (int i = 1; i < n; i++) {
        for (int prev = 0; prev < i; prev++) {
            if (arr[i] > arr[prev]) {
                lis[i] = max(lis[i], lis[prev] + 1);
            }
        }
    }

    // Return maximum value in lis
    return *max_element(lis.begin(), lis.end());
}

int main() {
    vector<int> arr = {3, 10, 2, 1, 20};
    cout << lis(arr) << endl;
    return 0;
}
Java
import java.util.Arrays;

class GFG {
    static int lis(int arr[]) {
        int n = arr.length;
        
        int lis[] = new int[n];
      
        // Initialize LIS values for all indexes
        Arrays.fill(lis, 1);

        // Compute optimized LIS values in
        // bottom up manner
        for (int i = 1; i < n; i++)
            for (int prev = 0; prev < i; prev++)
                if (arr[i] > arr[prev])
                    lis[i] = Math.max(lis[i], lis[prev] + 1);

        // Pick maximum of all LIS values
        int maxLen = 1;
        for (int i = 0; i < n; i++)
            maxLen = Math.max(maxLen, lis[i]);

        return maxLen;
    }

    public static void main(String args[]) {
        int arr[] = {3, 10, 2, 1, 20};
        System.out.println(lis(arr));
    }
}
Python
def lis(arr):
    n = len(arr)

    # Initialize LIS values 
    # for all indexes
    lis = [1] * n

    # Compute optimized LIS 
    # values in bottom-up manner
    for i in range(1, n):
        for prev in range(0, i):
            if arr[i] > arr[prev]:
                lis[i] = max(lis[i], lis[prev] + 1)

    # Return the maximum of all LIS values
    return max(lis)

if __name__ == '__main__':
    arr = [3, 10, 2, 1, 20]
    print(lis(arr))
C#
using System;

class GFG {
    static int lis(int[] arr) {
        int n = arr.Length;
        
        int[] lis = new int[n];

        // Initialize LIS values 
        // for all indexes
        for (int i = 0; i < n; i++)
            lis[i] = 1;

        // Compute optimized LIS 
        // values in bottom up manner
        for (int i = 1; i < n; i++) {
            for (int prev = 0; prev < i; prev++) {
                if(arr[i] > arr[prev])
                    lis[i] = Math.Max(lis[i], lis[prev] + 1);
            }
        }

        // Pick maximum among all LIS
        // lengths ending at any index
        int maxLen = 0;
        for (int i = 0; i < n; i++) {
                maxLen = Math.Max(maxLen, lis[i]);
        }

        return maxLen;
    }

    static void Main() {
        int[] arr = {3, 10, 2, 1, 20};
        Console.WriteLine(lis(arr));
    }
}
JavaScript
function lis(arr) {
    let n = arr.length;
    
    let lis = Array(n).fill(0);
    let max = 0;

    // Initialize LIS values for all indexes
    for (let i = 0; i < n; i++)
        lis[i] = 1;

    // Compute optimized LIS values in
    // bottom up manner 
    for (let i = 1; i < n; i++) {
        for (let prev = 0; prev < i; prev++) {
            if (arr[i] > arr[prev])
                lis[i] = Math.max(lis[i], lis[prev] + 1);
        }
    }

    let maxLen = 1;
    
    // Pick maximum of all LIS values 
    for (let i = 0; i < n; i++)
            maxLen = Math.max(maxLen, lis[i]);

    return maxLen;
}

// Driver code
let arr = [3, 10, 2, 1, 20];
console.log(lis(arr));

Output
4

[Expected Approach] Using Binary Search - O(n Log n) Time and O(n) Space

The idea is to simulate the process of finding a subsequence by maintaining a list of "buckets" where each bucket represents a valid subsequence. Initially, start with an empty list and iterate through the input vector arr from left to right.

For each number in arr, perform the following steps:

  • If the number is greater than the last element of the last bucket (i.e., the largest element in the current subsequence), we append the number to the end of the list. This indicates that we have found a longer subsequence.
  • Otherwise, perform a binary search on the list of buckets to find the smallest element that is greater than or equal to the current number. This step helps maintain the property of increasing elements in the buckets.
  • Once find the position to update, replace that element with the current number. This keeps the buckets sorted and ensures that we have the potential for a longer subsequence in the future.

Note: The resulting array only stores the length of longest increasing subsequence, and not the actual subsequence. Go through the illustration to clear this doubt.

Illustration:

Example: arr = [3, 10, 2, 1, 20], why keeping 1 (the smallest value) helps?

Use binary search to find the position where new element is to be inserted.

  1. First two elements: buckets = [3, 10]
  2. arr[2] = 2 buckets = [2, 10] -> replaces 3
  3. arr[3] = 1 buckets = [1, 10] -> 1 replaces 2 as it's smaller
  4. arr[4] = 20 buckets = [1, 10, 20] -> 20 is appended as it's larger

This shows that by replacing 3 with 1, we created the opportunity to find the subsequence [1, 10, 20], which is longer than our initial [3, 10]. If we had kept [3, 10], we wouldn't have been able to add 2 to our sequence!

The key insight is that keeping smaller values at each position:

  1. Maintains the same length information
  2. Creates more opportunities for future elements to form longer increasing subsequences
C++
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int lengthOfLIS(vector<int>& arr) {

    int n = arr.size();
    vector<int> ans;

    // Initialize the answer vector with the
    // first element of arr
    ans.push_back(arr[0]);

    for (int i = 1; i < n; i++) {
        if (arr[i] > ans.back()) {

            // If the current number is greater
            // than the last element of the answer
            // vector, it means we have found a
            // longer increasing subsequence.
            // Hence, we append the current number
            // to the answer vector.
            ans.push_back(arr[i]);
        }
        else {

            // If the current number is not
            // greater than the last element of
            // the answer vector, we perform
            // a binary search to find the smallest
            // element in the answer vector that
            // is greater than or equal to the
            // current number.

            // The lower_bound function returns
            // an iterator pointing to the first
            // element that is not less than
            // the current number.
            int low = lower_bound(ans.begin(), ans.end(),
                                  arr[i])
                      - ans.begin();

            // We update the element at the
            // found position with the current number.
            // By doing this, we are maintaining
            // a sorted order in the answer vector.
            ans[low] = arr[i];
        }
    }

    // The length of the answer vector
    // represents the length of the
    // longest increasing subsequence.
    return ans.size();
}

int main() {
    vector<int> arr = {3, 10, 2, 1, 20};
    cout << lengthOfLIS(arr) << "\n";
    return 0;
}
Java
import java.util.Arrays;

public class GFG {
    static int lengthOfLIS(int[] arr) {
        int n = arr.length;
        int[] ans = new int[n];
        int len = 0; 

        // Initialize the answer list with the
        // first element of arr
        ans[0] = arr[0];
        len = 1;

        for (int i = 1; i < n; i++) {
            if (arr[i] > ans[len - 1]) {
                // If the current number is greater
                // than the last element of the answer
                // list, it means we have found a
                // longer increasing subsequence.
                // Hence, we append the current number
                // to the answer list.
                ans[len] = arr[i];
                len++;
            } else {
                // If the current number is not
                // greater than the last element of
                // the answer list, we perform
                // a binary search to find the smallest
                // element in the answer list that
                // is greater than or equal to the
                // current number.

                // The binarySearch method returns
                // the index of the first element that is not less than
                // the current number.
                int low = Arrays.binarySearch(ans, 0, len, arr[i]);

                // We update the element at the
                // found position with the current number.
                // By doing this, we are maintaining
                // a sorted order in the answer list.
                if (low < 0) {
                    low = -(low + 1);
                }
                ans[low] = arr[i];
            }
        }

        // The size of the answer list
        // represents the length of the
        // longest increasing subsequence.
        return len;
    }

    // Driver program to test above function
    public static void main(String[] args) {
        int[] arr = {3, 10, 2, 1, 20};
        System.out.println(lengthOfLIS(arr));
    }
}
Python
def lengthOfLIS(arr):
    n = len(arr)
    ans = []

    # Initialize the answer list with the
    # first element of arr
    ans.append(arr[0])

    for i in range(1, n):
        if arr[i] > ans[-1]:
            # If the current number is greater
            # than the last element of the answer
            # list, it means we have found a
            # longer increasing subsequence.
            # Hence, we append the current number
            # to the answer list.
            ans.append(arr[i])
        else:
            # If the current number is not
            # greater than the last element of
            # the answer list, we perform
            # a binary search to find the smallest
            # element in the answer list that
            # is greater than or equal to the
            # current number.
            low = 0
            high = len(ans) - 1
            while low < high:
                mid = low + (high - low) // 2
                if ans[mid] < arr[i]:
                    low = mid + 1
                else:
                    high = mid
            # We update the element at the
            # found position with the current number.
            # By doing this, we are maintaining
            # a sorted order in the answer list.
            ans[low] = arr[i]

    # The length of the answer list
    # represents the length of the
    # longest increasing subsequence.
    return len(ans)

if __name__ == "__main__":
    arr = [3, 10, 2, 1, 20]
    print(lengthOfLIS(arr))
C#
using System;

class GFG {
    static int LengthOfLIS(int[] arr) {
        // Binary search approach
        int n = arr.Length;
        int[] ans = new int[n];
        int len = 0; // Tracks the current active length of the 'ans' array

        // Initialize the answer list with the
        // first element of arr
        ans[0] = arr[0];
        len = 1;

        for (int i = 1; i < n; i++) {
            if (arr[i] > ans[len - 1]) {
                // If the current number is greater
                // than the last element of the answer
                // list, it means we have found a
                // longer increasing subsequence.
                // Hence, we append the current number
                // to the answer list.
                ans[len] = arr[i];
                len++;
            }
            else {
                // If the current number is not
                // greater than the last element of
                // the answer list, we perform
                // a binary search to find the smallest
                // element in the answer list that
                // is greater than or equal to the
                // current number.

                // The BinarySearch method returns
                // the index of the first element that is not less than
                // the current number.
                int low = Array.BinarySearch(ans, 0, len, arr[i]);

                // We update the element at the
                // found position with the current number.
                // By doing this, we are maintaining
                // a sorted order in the answer list.
                if (low < 0) {
                    low = ~low;
                }
                ans[low] = arr[i];
            }
        }

        // The count of the answer list
        // represents the length of the
        // longest increasing subsequence.
        return len;
    }

    static void Main() {
        int[] arr = {3, 10, 2, 1, 20};
        Console.WriteLine(LengthOfLIS(arr));
    }
}
JavaScript
function lengthOfLIS(arr) {
    const n = arr.length;
    const ans = [];

    // Initialize the answer array with the first element of arr
    ans.push(arr[0]);

    for (let i = 1; i < n; i++) {
        if (arr[i] > ans[ans.length - 1]) {
            // If the current number is greater than the last element 
            // of the answer array, it means we have found a 
            // longer increasing subsequence. Hence, we push the current number
            // to the answer array.
            ans.push(arr[i]);
            
        } else {
            // If the current number is not greater than the last element of
            // the answer array, we perform a binary search to find the smallest
            // element in the answer array that is greater than or equal to the
            // current number.

            // Manual binary search to maintain O(log N) time complexity
            let low = 0;
            let high = ans.length - 1;
            while (low < high) {
                let mid = Math.floor((low + high) / 2);
                if (ans[mid] < arr[i]) {
                    low = mid + 1;
                } else {
                    high = mid;
                }
            }

            // We update the element at the found position with the current number.
            // By doing this, we are maintaining a sorted order in the answer array.
            ans[low] = arr[i];
        }
    }

    // The length of the answer array represents the length of the
    // longest increasing subsequence.
    return ans.length;
}

// Driver code
const arr = [3, 10, 2, 1, 20];
console.log(lengthOfLIS(arr));

Output
4

Problems based on LIS

Comment