Skip to content
geeksforgeeks
  • Courses
    • DSA to Development
    • Get IBM Certification
    • Newly Launched!
      • Master Django Framework
      • Become AWS Certified
    • For Working Professionals
      • Interview 101: DSA & System Design
      • Data Science Training Program
      • JAVA Backend Development (Live)
      • DevOps Engineering (LIVE)
      • Data Structures & Algorithms in Python
    • For Students
      • Placement Preparation Course
      • Data Science (Live)
      • Data Structure & Algorithm-Self Paced (C++/JAVA)
      • Master Competitive Programming (Live)
      • Full Stack Development with React & Node JS (Live)
    • Full Stack Development
    • Data Science Program
    • All Courses
  • Tutorials
    • Data Structures & Algorithms
    • ML & Data Science
    • Interview Corner
    • Programming Languages
    • Web Development
    • CS Subjects
    • DevOps And Linux
    • School Learning
  • Practice
    • Build your AI Agent
    • GfG 160
    • Problem of the Day
    • Practice Coding Problems
    • GfG SDE Sheet
  • Contests
    • Accenture Hackathon (Ending Soon!)
    • GfG Weekly [Rated Contest]
    • Job-A-Thon Hiring Challenge
    • All Contests and Events
  • DSA
  • Interview Problems on DP
  • Practice DP
  • MCQs on DP
  • Tutorial on Dynamic Programming
  • Optimal Substructure
  • Overlapping Subproblem
  • Memoization
  • Tabulation
  • Tabulation vs Memoization
  • 0/1 Knapsack
  • Unbounded Knapsack
  • Subset Sum
  • LCS
  • LIS
  • Coin Change
  • Word Break
  • Egg Dropping Puzzle
  • Matrix Chain Multiplication
  • Palindrome Partitioning
  • DP on Arrays
  • DP with Bitmasking
  • Digit DP
  • DP on Trees
  • DP on Graph
Open In App
Next Article:
Longest Increasing Subsequence (LIS)
Next article icon

Printing Longest Increasing Subsequence (LIS)

Last Updated : 07 May, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report
Try it on GfG Practice
redirect icon

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.

Table of Content

  • [Naive Approach]: Dynamic programming with Subsequence Storage – O(n^3) Time and O(n^2) Space
  • [Better Approach]: Dynamic programming with Single 1D Extra Array – O(n^2) Time and O(n) Space
  • [Expected Approach] Using DP with Binary Search – O(n*log(n)) Time and O(n) Space

[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.




Next Article
Longest Increasing Subsequence (LIS)

A

Aditya Goel
Improve
Article Tags :
  • DSA
  • Dynamic Programming
  • Binary Search
  • LIS
  • subsequence
Practice Tags :
  • Binary Search
  • Dynamic Programming

Similar Reads

  • Printing Longest Increasing Subsequence (LIS)
    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 lexicogr
    15+ min read
  • Longest Increasing Subsequence (LIS)
    Given an array arr[] of size n, the task is to 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 increasing order. Examples: Input: arr[] = [3, 10, 2, 1, 20]Output: 3Explanation: The longest incre
    14 min read
  • Printing longest Increasing consecutive subsequence
    Given n elements, write a program that prints the longest increasing subsequence whose adjacent element difference is one. Examples: Input : a[] = {3, 10, 3, 11, 4, 5, 6, 7, 8, 12} Output : 3 4 5 6 7 8 Explanation: 3, 4, 5, 6, 7, 8 is the longest increasing subsequence whose adjacent element differs
    8 min read
  • Printing Longest Bitonic Subsequence
    The Longest Bitonic Subsequence problem is to find the longest subsequence of a given sequence such that it is first increasing and then decreasing. A sequence, sorted in increasing order is considered Bitonic with the decreasing part as empty. Similarly, decreasing order sequence is considered Bito
    12 min read
  • Longest Increasing Subsequence Size (N log N)
    Given an array arr[] of size N, the task is to 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 increasing order, in O(N log N). Examples: Input: arr[] = {3, 10, 2, 1, 20}Output: 3Explanation: Th
    9 min read
  • Printing Longest Common Subsequence
    Given two sequences, print the longest subsequence present in both of them. Examples: LCS for input Sequences “ABCDGH” and “AEDFHR” is “ADH” of length 3. LCS for input Sequences “AGGTAB” and “GXTXAYB” is “GTAB” of length 4.We have discussed Longest Common Subsequence (LCS) problem in a previous post
    15+ min read
  • Minimizing and Maximizing longest Increasing Subsequence (LIS)
    Given a string S of length n-1, consisting of characters '<' and '>' only. The ith character is the comparison result between the ith element and the (i+1)th element of the sequence. If the ith character of the string is '<', then the ith element of the sequence is less than the (i+1)st ele
    9 min read
  • Length of longest increasing subsequence in a string
    Given a string S, the task is to find the length of the longest increasing subsequence present in the given string. A sequence of characters placed in increasing order of their ASCII values is called an increasing sequence. Examples: Input: S = "abcfgffs"Output: 6Explanation: Subsequence "abcfgs" is
    7 min read
  • Longest Common Increasing Subsequence (LCS + LIS)
    Given two arrays, a[] and b[], find the length of the longest common increasing subsequence(LCIS). LCIS refers to a subsequence that is present in both arrays and strictly increases.Prerequisites: LCS, LIS. Examples: Input: a[] = [3, 4, 9, 1], b[] = [5, 3, 8, 9, 10, 2, 1]Output: 2Explanation: The lo
    15+ min read
  • Printing Maximum Sum Increasing Subsequence
    The Maximum Sum Increasing Subsequence problem is to find the maximum sum subsequence of a given sequence such that all elements of the subsequence are sorted in increasing order. Examples: Input: [1, 101, 2, 3, 100, 4, 5]Output: [1, 2, 3, 100]Input: [3, 4, 5, 10]Output: [3, 4, 5, 10]Input: [10, 5,
    15 min read
geeksforgeeks-footer-logo
Corporate & Communications Address:
A-143, 7th Floor, Sovereign Corporate Tower, Sector- 136, Noida, Uttar Pradesh (201305)
Registered Address:
K 061, Tower K, Gulshan Vivante Apartment, Sector 137, Noida, Gautam Buddh Nagar, Uttar Pradesh, 201305
GFG App on Play Store GFG App on App Store
Advertise with us
  • Company
  • About Us
  • Legal
  • Privacy Policy
  • In Media
  • Contact Us
  • Advertise with us
  • GFG Corporate Solution
  • Placement Training Program
  • Languages
  • Python
  • Java
  • C++
  • PHP
  • GoLang
  • SQL
  • R Language
  • Android Tutorial
  • Tutorials Archive
  • DSA
  • Data Structures
  • Algorithms
  • DSA for Beginners
  • Basic DSA Problems
  • DSA Roadmap
  • Top 100 DSA Interview Problems
  • DSA Roadmap by Sandeep Jain
  • All Cheat Sheets
  • Data Science & ML
  • Data Science With Python
  • Data Science For Beginner
  • Machine Learning
  • ML Maths
  • Data Visualisation
  • Pandas
  • NumPy
  • NLP
  • Deep Learning
  • Web Technologies
  • HTML
  • CSS
  • JavaScript
  • TypeScript
  • ReactJS
  • NextJS
  • Bootstrap
  • Web Design
  • Python Tutorial
  • Python Programming Examples
  • Python Projects
  • Python Tkinter
  • Python Web Scraping
  • OpenCV Tutorial
  • Python Interview Question
  • Django
  • Computer Science
  • Operating Systems
  • Computer Network
  • Database Management System
  • Software Engineering
  • Digital Logic Design
  • Engineering Maths
  • Software Development
  • Software Testing
  • DevOps
  • Git
  • Linux
  • AWS
  • Docker
  • Kubernetes
  • Azure
  • GCP
  • DevOps Roadmap
  • System Design
  • High Level Design
  • Low Level Design
  • UML Diagrams
  • Interview Guide
  • Design Patterns
  • OOAD
  • System Design Bootcamp
  • Interview Questions
  • Inteview Preparation
  • Competitive Programming
  • Top DS or Algo for CP
  • Company-Wise Recruitment Process
  • Company-Wise Preparation
  • Aptitude Preparation
  • Puzzles
  • School Subjects
  • Mathematics
  • Physics
  • Chemistry
  • Biology
  • Social Science
  • English Grammar
  • Commerce
  • World GK
  • GeeksforGeeks Videos
  • DSA
  • Python
  • Java
  • C++
  • Web Development
  • Data Science
  • CS Subjects
@GeeksforGeeks, Sanchhaya Education Private Limited, All rights reserved
We use cookies to ensure you have the best browsing experience on our website. By using our site, you acknowledge that you have read and understood our Cookie Policy & Privacy Policy
Lightbox
Improvement
Suggest Changes
Help us improve. Share your suggestions to enhance the article. Contribute your expertise and make a difference in the GeeksforGeeks portal.
geeksforgeeks-suggest-icon
Create Improvement
Enhance the article with your expertise. Contribute to the GeeksforGeeks community and help create better learning resources for all.
geeksforgeeks-improvement-icon
Suggest Changes
min 4 words, max Words Limit:1000

Thank You!

Your suggestions are valuable to us.

What kind of Experience do you want to share?

Interview Experiences
Admission Experiences
Career Journeys
Work Experiences
Campus Experiences
Competitive Exam Experiences