Open In App

Printing Longest Increasing Subsequence (LIS)

Last Updated : 07 May, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

Given a sequence of numbers, the task is to find and print the Longest Increasing Subsequence (LIS), the longest subsequence where each element is strictly greater than the previous one. If multiple LIS of the same maximum length exist, we must select the one that appears first based on the lexicographical order of their indices (i.e., the earliest combination of positions from the original sequence). The goal is to ensure both maximum length and the earliest possible subsequence.

Examples:  

Input:  [10, 20, 3, 40]
Output : 10 20 40
Explanation: [10, 20, 40] is the longest subsequence where each number is greater than the previous one, maintaining the original order

Input:  [10, 22, 9, 33, 21, 50, 41, 60, 80]
Output : 10 22 33 50 60 80
Explanation: There are multiple longest Increasing subsequence of length 6, examples [10, 22, 33, 50, 60, 80] and [10 22 33 41 60 80]. The first one has lexicographic smallest order.

[Naive Approach]: Dynamic programming with Subsequence Storage - O(n^3) Time and O(n^2) Space

We extend the of bottom-up DP solution of LIS problem. Please remember, for every element arr[i], it iterates over all previous elements (arr[prev] where prev < i) to find the longest subsequence that can be extended by arr[i]. To find elements of LIS, we build an array of arrays, L such that L[i] stores LIS of arr that ends with arr[i]. For example, for array [3, 2, 6, 4, 5, 1].

L[0] = [3]
L[1] = [2]
L[2] = [2, 6]
L[3] = [2, 4]
L[4] = [2, 4, 5]
L[5] = [1]

The final result is the longest subsequence among all L[i].

Step by step Approach

  • Create an array of arrays L where L[i] stores the longest increasing subsequence (LIS) ending at index i.
  • Initialize L[0] with the first element (arr[0]), as it’s the only subsequence possible at this point.
  • For each element arr[i] (starting from i=1 to n-1):
    • Check all previous indices prev (from 0 to i-1).
    • If arr[i] > arr[prev] (valid to extend the subsequence) and the subsequence L[prev] is longer than the current best for L[i]: Update L[i] by copying L[prev] (this extends the subsequence ending at prev).
    • Append arr[i] to L[i] (since arr[i] is the endpoint of this subsequence).
  • After processing all elements, iterate through L[0] to L[n-1] to find the longest subsequence in L, which is the LIS.
C++
#include <iostream>
#include <vector>
using namespace std;

// Function to construct and print Longest 
// Increasing Subsequence
vector<int> getLIS(vector<int>& arr){
    
    // L[i] - The longest increasing 
    // sub-sequence ends with arr[i]
    int n = arr.size();
    vector<vector<int>> L(n);

    // L[0] is equal to arr[0]
    L[0].push_back(arr[0]);

    // Start from index 1
    for (int i = 1; i < n; i++){
        
        int lis = 1;

        // Do for every prev less than i
        for (int prev = 0; prev < i; prev++){
            
            /* L[i] = {Max(L[prev])} + arr[i]
               where prev < i and arr[prev] < arr[i] */
            if ((arr[i] > arr[prev]) && 
                (lis < L[prev].size() + 1)) {
              
                // Copy the vector of prev and update lis of i
                L[i] = L[prev];
                lis = L[prev].size() + 1;
            }
        }

        // L[i] ends with arr[i]
        L[i].push_back(arr[i]);
    }

    // L[i] now stores increasing sub-sequence 
    // of arr[0..i] that ends with arr[i]
    vector<int> res = L[0];

    // LIS will be max of all increasing 
    // sub-sequences of arr
    for (vector<int> x : L)
        if (x.size() > res.size())
            res = x;
    return res;
}

// Driver function
int main(){

    vector<int> arr = {10, 20, 3, 40};
    
    vector<int> max_lis = getLIS(arr);
    for (int x : max_lis)
        cout << x << " ";
    return 0;
}
Java
import java.util.ArrayList;
import java.util.List;

class GfG {


    // Function to construct and print Longest
    // Increasing Subsequence
    static ArrayList<Integer> getLIS(int arr[]) {
    
    int n = arr.length;
    
    // L[i] - The longest increasing subsequence ending with arr[i]
    List<List<Integer>> L = new ArrayList<>();

    // Initialize L[i] as empty lists
    for (int i = 0; i < n; i++) {
        L.add(new ArrayList<>());
    }

    // Base case: first element
    L.get(0).add(arr[0]);

    // Build the LIS lists
    for (int i = 1; i < n; i++) {
    int lis = 1;

    for (int prev = 0; prev < i; prev++) {
        if (arr[i] > arr[prev] && lis < L.get(prev).size() + 1) {
            L.set(i, new ArrayList<>(L.get(prev)));
            lis = L.get(prev).size() + 1;
        }
    }

    L.get(i).add(arr[i]);
   }

    // Find the list with the maximum length
    ArrayList<Integer> res = new ArrayList<>(L.get(0));

    for (List<Integer> x : L) {
        if (x.size() > res.size()) {
            res = new ArrayList<>(x);
        }
    }

    return res;
        
    }

    // Driver function
    public static void main(String[] args) {
        int[] arr = {10, 20, 3, 40};
        ArrayList<Integer> max_lis = getLIS(arr);
        for (int i = 0; i < max_lis.size(); i++) {
            System.out.print(max_lis.get(i) + " ");
        }

    }
}
Python
def getLIS(arr):
    n = len(arr)
    
    # L[i] - The longest increasing sub-sequence ends with arr[i]
    L = [[] for _ in range(n)]

    # L[0] is equal to arr[0]
    L[0].append(arr[0])

    # Start from index 1
    for i in range(1, n):
        lis = 1
        
        # Do for every prev less than i
        for prev in range(i):
            if arr[i] > arr[prev] and lis < len(L[prev]) + 1:
              
                # Copy the list of prev and update lis of i
                L[i] = L[prev][:]
                lis = len(L[prev]) + 1

        # L[i] ends with arr[i]
        L[i].append(arr[i])

    # L[i] now stores increasing sub-sequence
    # of arr[0..i] that ends with arr[i]
    res = L[0]

    # LIS will be max of all increasing 
    # sub-sequences of arr
    for x in L:
        if len(x) > len(res):
            res = x

    # return the longest increasing subsequence
    return res
    
# Driver function
if __name__ == "__main__":
    arr = [10, 20, 3, 40]
    
    # Construct and print LIS of arr
    max_lis = getLIS(arr)
    print(" ".join(map(str, max_lis)))
C#
using System;
using System.Collections.Generic;

class GfG
{
    // Function to construct and return the Longest Increasing Subsequence
    static List<int> getLIS(int[] arr)
    {    
        int n = arr.Length;
        // L[i] - The longest increasing subsequence ending with arr[i]
        List<List<int>> L = new List<List<int>>(n);

        // Initialize the lists
        for (int i = 0; i < n; i++)
        {
            L.Add(new List<int>());
        }

        // Base case: first element
        L[0].Add(arr[0]);

        // Build the LIS lists
        for (int i = 1; i < n; i++)
        {
            int lis = 1;

            for (int prev = 0; prev < i; prev++)
            {
                if (arr[i] > arr[prev] && lis < L[prev].Count + 1)
                {
                    // Copy the best previous subsequence
                    L[i] = new List<int>(L[prev]);
                    lis = L[prev].Count + 1;
                }
            }

            // Append current element
            L[i].Add(arr[i]);
        }

        // Find the list with the maximum length
        List<int> res = new List<int>(L[0]);
        foreach (List<int> x in L)
        {
            if (x.Count > res.Count)
            {
                res = x;
            }
        }

        return res;
    }

    // Driver function
    static void Main(){
        
        int[] arr = {10, 20, 3, 40 };
       
        List<int> max_lis = getLIS(arr);

        foreach (int x in max_lis){
            
            Console.Write(x + " ");
        }
        Console.WriteLine();
    }
}
JavaScript
// Function to construct and print Longest
// Increasing Subsequence
function getLIS(arr) {
    const n = arr.length;
    
    // L[i] - The longest increasing sub-sequence 
    // ends with arr[i]
    const L = Array.from({ length: n }, () => []);

    // L[0] is equal to arr[0]
    L[0].push(arr[0]);

    // Start from index 1
    for (let i = 1; i < n; i++) {
        let lis = 1;

        // Do for every prev less than i
        for (let prev = 0; prev < i; prev++) {
        
            if (arr[i] > arr[prev] && lis < L[prev].length + 1) {
                // Copy the list of prev and update lis of i
                L[i] = [...L[prev]];
                lis = L[prev].length + 1;
            }
        }

        // L[i] ends with arr[i]
        L[i].push(arr[i]);
    }

    // L[i] now stores increasing sub-sequence
    // of arr[0..i] that ends with arr[i]
    let res = L[0];

    // LIS will be max of all increasing 
    // sub-sequences of arr
    for (const x of L) {
        if (x.length > res.length) {
            res = x;
        }
    }

    // Return the longest increasing subsequence
    return res;
}

// Driver function
const arr = [10, 20, 3, 40];
let max_lis = getLIS(arr);
console.log(max_lis.join(' '));

Output
10 20 40 

Time Complexity: O(n3), n2 for two nested loops and n for copying another vector in a vector (e.g. : L[i] = L[prev]) contributes O(n) also.
Space Complexity: O(n2), 2d vector to store our LIS

[Better Approach]: Dynamic programming with Single 1D Extra Array - O(n^2) Time and O(n) Space

In the previous solution, we use an array of arrays to store all subsequences ending with every index. The idea here is to store only indexes of only the previous item in the answer LIS.

  1. We use an array seq[] to store indexes of previous items in LIS and used to construct the resultant sequence. Along with constructing dp[] array, we fill indexes in seq[].
  2. After filling seq[] and dp[], we find the index of the largest element in dp.
  3. Now using the index found in step 2 and seq[], we construct the result sequence.
C++
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

// Function to find the longest increasing 
// subsequence.
vector<int> getLIS(vector<int>& arr) {
   
    int n = arr.size();
  
    // Initialize dp array with 1.
    vector<int> dp(n, 1);
  
    // Initialize hash array with index values.
    // We store previous indexs in LIS here
    vector<int> seq(n);

    for (int i = 0; i < n; i++) {
      
        seq[i] = i; // Mark element itself as prev
      
        for (int prev = 0; prev < i; prev++) {
          
            // Update dp and hash values if 
            // condition satisfies.
            if (arr[prev] < arr[i] && 
                1 + dp[prev] > dp[i]) {
              
                dp[i] = 1 + dp[prev];
                seq[i] = prev;
            }
        }
    }

    // Now we find the last element 
    // in LIS using dp[]
    int ans = -1;
    int ansInd = -1;
    for (int i = 0; i < n; i++) {
        if (dp[i] > ans) {
            ans = dp[i];
            ansInd = i;
        }
    }

    // Now construct result sequence using seq[]
    // and ans_ind
    vector<int> res;
    res.push_back(arr[ansInd]);
    while (seq[ansInd] != ansInd) {
        ansInd = seq[ansInd];
        res.push_back(arr[ansInd]);
    }
    reverse(res.begin(), res.end());
    return res;
}

int main() {
    vector<int> arr = {10, 20, 3, 40};

    vector<int> max_lis = getLIS(arr);

    for (int num : max_lis) {
        cout << num << " ";
    }
    cout << endl;

    return 0;
}
Java
import java.util.ArrayList;
import java.util.Collections;

public class Main {

    // Function to find the longest increasing subsequence
    public static ArrayList<Integer> getLIS(int[] arr) {
        int n = arr.length;

        // Initialize dp array with 1
        int[] dp = new int[n];
        for (int i = 0; i < n; i++) {
            dp[i] = 1;
        }

        // Initialize seq array with index values (to store previous indices in LIS)
        int[] seq = new int[n];
        for (int i = 0; i < n; i++) {
            seq[i] = i;
        }

        // Compute dp and seq arrays
        for (int i = 0; i < n; i++) {
            for (int prev = 0; prev < i; prev++) {
                if (arr[prev] < arr[i] && 1 + dp[prev] > dp[i]) {
                    dp[i] = 1 + dp[prev];
                    seq[i] = prev;
                }
            }
        }

        // Find the index of the last element in the LIS
        int ans = -1;
        int ansInd = -1;
        for (int i = 0; i < n; i++) {
            if (dp[i] > ans) {
                ans = dp[i];
                ansInd = i;
            }
        }

        // Construct the result sequence using seq array
        ArrayList<Integer> res = new ArrayList<>();
        res.add(arr[ansInd]);
        while (seq[ansInd] != ansInd) {
            ansInd = seq[ansInd];
            res.add(arr[ansInd]);
        }

        // Reverse the result to get the correct order
        Collections.reverse(res);
        return res;
    }

    public static void main(String[] args) {
        int[] arr = {10, 20, 3, 40};

        ArrayList<Integer> max_lis = getLIS(arr);

        for (int i = 0; i < max_lis.size(); i++) {
            System.out.print(max_lis.get(i) + " ");
        }

    }
}
Python
# Function to find the longest increasing subsequence
def getLIS(arr):
    n = len(arr)

    # Initialize dp array with 1
    dp = [1] * n

    # Initialize seq array with index values (to store previous indices in LIS)
    seq = list(range(n))

    # Compute dp and seq arrays
    for i in range(n):
        for prev in range(i):
            if arr[prev] < arr[i] and 1 + dp[prev] > dp[i]:
                dp[i] = 1 + dp[prev]
                seq[i] = prev

    # Find the index of the last element in the LIS
    ans = -1
    ans_ind = -1
    for i in range(n):
        if dp[i] > ans:
            ans = dp[i]
            ans_ind = i

    # Construct the result sequence using seq array
    res = []
    res.append(arr[ans_ind])
    while seq[ans_ind] != ans_ind:
        ans_ind = seq[ans_ind]
        res.append(arr[ans_ind])

    # Reverse the result to get the correct order
    res.reverse()
    return res

if __name__ == "__main__":
    arr = [10, 20, 3, 40]

    max_lis = getLIS(arr)

    print(" ".join(map(str, max_lis)))
C#
using System;
using System.Collections.Generic;

class GfG{
    // Function to find the longest increasing subsequence
    static List<int> getLIS(int[] arr){
        
        int n = arr.Length;

        // Initialize dp array with 1
        int[] dp = new int[n];
        for (int i = 0; i < n; i++)
        {
            dp[i] = 1;
        }

        // Initialize seq array with index values (to store previous indices in LIS)
        int[] seq = new int[n];
        for (int i = 0; i < n; i++)
        {
            seq[i] = i;
        }

        // Compute dp and seq arrays
        for (int i = 0; i < n; i++)
        {
            for (int prev = 0; prev < i; prev++)
            {
                if (arr[prev] < arr[i] && 1 + dp[prev] > dp[i])
                {
                    dp[i] = 1 + dp[prev];
                    seq[i] = prev;
                }
            }
        }

        // Find the index of the last element in the LIS
        int ans = -1;
        int ansInd = -1;
        for (int i = 0; i < n; i++)
        {
            if (dp[i] > ans)
            {
                ans = dp[i];
                ansInd = i;
            }
        }

        // Construct the result sequence using seq array
        List<int> res = new List<int>();
        res.Add(arr[ansInd]);
        while (seq[ansInd] != ansInd)
        {
            ansInd = seq[ansInd];
            res.Add(arr[ansInd]);
        }

        // Reverse the result to get the correct order
        res.Reverse();
        return res;
    }

    static void Main(string[] args)
    {
        int[] arr = {10, 20, 3, 40};

        List<int> max_lis = getLIS(arr);

        Console.WriteLine(string.Join(" ", max_lis));
    }
}
JavaScript
// Function to find the longest increasing subsequence
function getLIS(arr) {
    const n = arr.length;

    // Initialize dp array with 1
    const dp = new Array(n).fill(1);

    // Initialize seq array with index values (to store previous indices in LIS)
    const seq = [...Array(n).keys()];

    // Compute dp and seq arrays
    for (let i = 0; i < n; i++) {
        for (let prev = 0; prev < i; prev++) {
            if (arr[prev] < arr[i] && 1 + dp[prev] > dp[i]) {
                dp[i] = 1 + dp[prev];
                seq[i] = prev;
            }
        }
    }

    // Find the index of the last element in the LIS
    let ans = -1;
    let ansInd = -1;
    for (let i = 0; i < n; i++) {
        if (dp[i] > ans) {
            ans = dp[i];
            ansInd = i;
        }
    }

    // Construct the result sequence using seq array
    const res = [];
    res.push(arr[ansInd]);
    while (seq[ansInd] !== ansInd) {
        ansInd = seq[ansInd];
        res.push(arr[ansInd]);
    }

    // Reverse the result to get the correct order
    res.reverse();
    return res;
}

const arr = [10, 20, 3, 40];

const max_lis = getLIS(arr);

console.log(max_lis.join(" "));

Output
10 20 40 

Time Complexity: O(n2), We have two nested loops: one to fill the dp[] array and another to backtrack using the seq[]array.
Space Complexity: O(n), We use two arrays, dp[]and seq[], each of size n.

[Expected Approach] Using DP with Binary Search - O(n*log(n)) Time and O(n) Space

The idea is based on LIS using binary search to improve efficiency. We maintain a list (dp) representing the minimum possible last value for increasing subsequences of different lengths. We process elements backward and use negative values to flip the problem into a decreasing order, making it easier to find the correct position using binary search function like lower_bound() in C++. Tracking previous indices allows us to reconstruct the actual sequence after processing. This method ensures both maximum length and earliest lexicographical order efficiently.

Step by Step Approach

  • Create an empty list dp to store pairs (-value, index).
  • Create a map prv to remember the previous index for each element.
  • Iterate from the last element to the first.
  • For each element, take its negative (ve = -arr[ix]) to handle increasing order via decreasing values.
  • Use binary search (lower_bound) to find the right position in dp.
  • If the position is at the end of dp, append the element and set its previous index.
  • Else, update dp[i] with the current value and set its previous link.
  • Start from the last element's index (from dp.back().second).
  • Follow previous pointers (prv[cur]) to collect elements into the result list.
  • Since we built the sequence backward, finally reverse the ret array to get the LIS in correct order.
C++
#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_map>

using namespace std;

vector<int> getLIS(int N, vector<int>& arr) {
    vector<pair<int, int>> dp;  
    unordered_map<int, int> prv;
    
    // Process array in reverse order
    for (int ix = N - 1; ix >= 0; --ix) {
        int ve = -arr[ix];  
        
        // Binary search to find insertion point
        auto it = lower_bound(dp.begin(), dp.end(), make_pair(ve, 0),
             [](const pair<int, int>& a, const pair<int, int>& b) {
                 return a.first < b.first;
             });
        
        int tmp = -1;  // Default previous index
        int i = distance(dp.begin(), it);
        
        if (i == dp.size()) {
            if (!dp.empty()) {
                tmp = dp.back().second;
            }
            dp.emplace_back(ve, ix);
        } else {
            if (i > 0) {
                tmp = dp[i-1].second;
            }
            dp[i] = {ve, ix};
        }
        prv[ix] = tmp;
    }
    
    // Reconstruct the LIS
    vector<int> ret;
    int cur = dp.back().second;
    while (cur >= 0) {
        ret.push_back(arr[cur]);
        cur = prv[cur];
    }

    return ret;
}

int main() {
    vector<int> arr = {10, 20, 3, 40};
    vector<int> lis = getLIS(arr.size(), arr);
    
    for (int num : lis) {
        cout << num << " ";
    }
    return 0;
}
Java
import java.util.*;

public class Solution {
    // Function to find Longest Increasing Subsequence
    static ArrayList<Integer> getLIS(int arr[]) {
        ArrayList<Integer> ret = new ArrayList<>();
        ArrayList<int[]> dp = new ArrayList<>();  
        HashMap<Integer, Integer> prv = new HashMap<>();  
        int N = arr.length;

        // Process array in reverse order
        for (int ix = N - 1; ix >= 0; --ix) {
            
            // Using negative for bisect_left equivalent
            int ve = -arr[ix];  

            // Binary search to find insertion point
            int l = 0, r = dp.size();
            while (l < r) {
                int m = l + (r - l) / 2;
                if (dp.get(m)[0] < ve) {
                    l = m + 1;
                } else {
                    r = m;
                }
            }
            int i = l;
            
            int tmp = -1;  
            
            if (i == dp.size()) {
                if (!dp.isEmpty()) {
                    tmp = dp.get(dp.size() - 1)[1];
                }
                dp.add(new int[]{ve, ix});
            } else {
                if (i > 0) {
                    tmp = dp.get(i - 1)[1];
                }
                dp.set(i, new int[]{ve, ix});
            }
            prv.put(ix, tmp);
        }

        // Reconstruct the LIS
        int cur = dp.get(dp.size() - 1)[1];
        while (cur >= 0) {
            ret.add(arr[cur]);
            cur = prv.getOrDefault(cur, -1);
        }
        return ret;
    }

    public static void main(String[] args) {
        int[] arr = {10, 20, 3, 40};
        ArrayList<Integer> lis = getLIS(arr);
        System.out.println(lis);
    }
}
Python
def getLIS(arr):
    ret = []  
    dp = []  
    prv = {} 
    N = len(arr)

    # Process array in reverse order
    for ix in range(N - 1, -1, -1):
        
        # Using negative for bisect_left equivalent
        ve = -arr[ix] 

        # Binary search to find insertion point
        l, r = 0, len(dp)
        while l < r:
            m = l + (r - l) // 2
            if dp[m][0] < ve:
                l = m + 1
            else:
                r = m
        i = l
        
        # Default previous index
        tmp = -1  

        if i == len(dp):
            if dp:
                tmp = dp[-1][1]
            dp.append((ve, ix))
        else:
            if i > 0:
                tmp = dp[i - 1][1]
            dp[i] = (ve, ix)

        prv[ix] = tmp

    # Reconstruct the LIS
    cur = dp[-1][1]
    while cur >= 0:
        ret.append(arr[cur])
        cur = prv.get(cur, -1)

    return ret

# Example usage
arr = [10, 20, 3, 40]
print(getLIS(arr))
C#
using System;
using System.Collections.Generic;

public class Solution {
    // Function to find Longest Increasing Subsequence
    public List<int> getLIS(List<int> arr) {
        List<int> ret = new List<int>();
        List<(int, int)> dp = new List<(int, int)>();  // Stores (-value, index) pairs
        Dictionary<int, int> prv = new Dictionary<int, int>();  // Stores previous index for each element
        int N = arr.Count;

        // Process array in reverse order
        for (int ix = N - 1; ix >= 0; --ix) {
            int ve = -arr[ix];  

            // Binary search to find insertion point
            int l = 0, r = dp.Count;
            while (l < r) {
                int m = l + (r - l) / 2;
                if (dp[m].Item1 < ve) {
                    l = m + 1;
                } else {
                    r = m;
                }
            }
            int i = l;
            
            // Default previous index
            int tmp = -1;  

            if (i == dp.Count) {
                if (dp.Count > 0) {
                    tmp = dp[dp.Count - 1].Item2;
                }
                dp.Add((ve, ix));
            } else {
                if (i > 0) {
                    tmp = dp[i - 1].Item2;
                }
                dp[i] = (ve, ix);
            }
            prv[ix] = tmp;
        }

        // Reconstruct the LIS
        int cur = dp[dp.Count - 1].Item2;
        while (cur >= 0) {
            ret.Add(arr[cur]);
            cur = prv.ContainsKey(cur) ? prv[cur] : -1;
        }
        
        return ret;
    }

    public static void Main(string[] args) {
        List<int> arr = new List<int> {10, 20, 3, 40};
        Solution sol = new Solution();
        List<int> lis = sol.getLIS(arr);
        Console.WriteLine(string.Join(" ", lis));
    }
}
JavaScript
function getLIS(arr) {
    let ret = [];  
    let dp = [];  
    let prv = {}; 
    let N = arr.length;

    // Process array in reverse order
    for (let ix = N - 1; ix >= 0; --ix) {
        let ve = -arr[ix];  
        
        // Binary search to find insertion point
        let l = 0, r = dp.length;
        while (l < r) {
            let m = l + Math.floor((r - l) / 2);
            if (dp[m][0] < ve) {
                l = m + 1;
            } else {
                r = m;
            }
        }
        let i = l;
        
        // Default previous index
        let tmp = -1;  

        if (i === dp.length) {
            if (dp.length > 0) {
                tmp = dp[dp.length - 1][1];
            }
            dp.push([ve, ix]);
        } else {
            if (i > 0) {
                tmp = dp[i - 1][1];
            }
            dp[i] = [ve, ix];
        }
        prv[ix] = tmp;
    }

    // Reconstruct the LIS
    let cur = dp[dp.length - 1][1];
    while (cur >= 0) {
        ret.push(arr[cur]);
        cur = prv[cur] !== undefined ? prv[cur] : -1;
    }

    return ret;
}

// Driver Code
const arr = [10, 20, 3, 40];
console.log(getLIS(arr));

Output
10 20 40 

Time Complexity: O(N log N) ,for each of the N elements we perform a binary search (using lower_bound) in the dp array, which takes O(log N) time. Thus, processing all elements gives an overall complexity of O(N log N).
Auxiliary space: O(N), we use extra space for the dp list and the prv map, both of which at most store one entry per element in the input array.



Similar Reads