Open In App

Find the Second Longest Increasing Subsequence

Last Updated : 14 Apr, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given an array arr[] of integers, the task is to find the length of the second longest increasing subsequence (LIS).

Examples:

Input: arr[] = {1, 2, 3, 4}
Output:
Explanation: Here the length of LIS is 4 which is whole array and length of second LIS is 3 which can be any sequence, {1, 2, 3} or {1, 2, 4} or {1, 3, 4} or {2, 3, 4}.

Input: arr[] = {1, -4, 3, 5, 9}
Output:
Explanation: Here the length of LIS is 4. Second LIS is also 4, because there can be two sequence in this case with length 4. One is {1, 3, 5, 9} and second is {-4, 3, 5, 9}.

Approach: To solve the problem follow the below idea:

  • In order to solve this problem we first find the length of the longest increasing subsequence(LIS). This can be done with a time complexity of O(n^2) using dynamic programming. Along with this, we find the count of the number of subsequences which has a length of LIS. Here is an article where the approach to find the count of LIS.
  • After finding the count of LIS in an array we check if the count of such subsequence with same length of LIS is more than two or not, if yes then it means that more than one LIS is present and hence the length of the second longest subsequence will also be lengthOfLis. If the count is not greater than 1 then the second longest subsequence can be lengthOfLis -1 as the second longest subsequence can be subset of LIS with any one element excluded.

Steps involved in the implementation of the code:

  • Initialize two arrays dpL[] and dpC[]. Here dpL[] stores the length of the longest increasing subsequences and dpC[] stores the count of the longest increasing subsequence at each index respectively.
  • Traverse the array using two loops where variable i iterates from 0 to n-1 and variable j iterates from 0 to i – 1.
  • If arr[i] > arr[j] then check for the following two cases.
  • If (dpL[j]+1) is greater than dpL[i], then update dpL[i] as dpL[j] + 1 and dpC[i] as dpC[j].
  • Else if (dpL[j] + 1) is the same as dpL[i], then update dpC[i] as dpC[i] + dpC[j].
  • Then find the maximum element in the array dpL[] and store it in a variable maxLength as it is the longest increasing subsequence.
  • Initialize a variable count with 0 to store the number of the longest increasing subsequence. Then traverse the array dpL[] and if at any index i, dpL[i] is the same as maxLength then increment the count by dpC[i].
  • If the count of the longest increasing subsequence is greater than 1 then return maxLength else return maxLength – 1.

Below is the implementation for the above approach:

C++

// C++ code for above approach
#include <bits/stdc++.h>
using namespace std;

// Function to find the second
// longest increasing subsequence
int secondLis(int arr[], int n)
{

    // Initialize dpL array with
    // 1 which Store the length of
    // the longest increasing subsequences
    vector<int> dpL(n, 1);

    // Initialize dpC array with
    // 1 which store the count of
    // the longest increasing
    // subsequence at each index
    vector<int> dpC(n, 1);

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < i; j++) {
            // If current element is
            // smaller
            if (arr[i] <= arr[j])
                continue;

            if (dpL[j] + 1 > dpL[i]) {
                // If new longer lis found,
                // update current length
                // max upto this index as
                // dpL[j]+1, and also
                // update count of current
                // size as that of dpC[j]th
                dpL[i] = dpL[j] + 1;
                dpC[i] = dpC[j];
            }
            else if (dpL[j] + 1 == dpL[i])

                // Else if similar length,
                // add up ith index count
                // with jth.
                dpC[i] += dpC[j];
        }
    }

    // Finding length of LIS
    int maxLength = 0;
    for (int i : dpL)
        maxLength = max(i, maxLength);

    // Stores the count of LIS
    int count = 0;

    // Finding count
    for (int i = 0; i < n; i++) {

        // Update the count
        if (dpL[i] == maxLength)
            count += dpC[i];
    }

    // If count is more than 1 LIS
    // then second longest will be
    // same as length of LIS(maxLength)
    // else it will be maxLength-1
    if (count > 1) {
        return maxLength;
    }
    else {
        return maxLength - 1;
    }
}

// Driver's code
int main()
{
    int arr[] = { 1, -4, 3, 5, 9 };
    int n = sizeof(arr) / sizeof(arr[0]);
    printf("Length of second longest increasing "
           "subsequence is %d\n",
           secondLis(arr, n));

    return 0;
}

Java

// Java code for above approach
import java.util.*;

class GFG {

  // Function to find the second
  // longest increasing subsequence
  public static int secondLis(int arr[], int n)
  {
    // Initialize dpL array with
    // 1 which Store the length of
    // the longest increasing subsequences
    int dpL[] = new int[n];
    Arrays.fill(dpL, 1);

    // Initialize dpC array with
    // 1 which store the count of
    // the longest increasing
    // subsequence at each index
    int dpC[] = new int[n];
    Arrays.fill(dpC, 1);

    for (int i = 0; i < n; i++) {
      for (int j = 0; j < i; j++) {
        // If current element is
        // smaller
        if (arr[i] <= arr[j])
          continue;

        if (dpL[j] + 1 > dpL[i]) {

          // If new longer lis found,
          // update current length
          // max upto this index as
          // dpL[j]+1, and also
          // update count of current
          // size as that of dpC[j]th
          dpL[i] = dpL[j] + 1;
          dpC[i] = dpC[j];
        }
        else if (dpL[j] + 1 == dpL[i]) {
          // Else if similar length,
          // add up ith index count
          // with jth.
          dpC[i] += dpC[j];
        }
      }
    }

    // Finding length of LIS
    int maxLength = 0;
    for (int i : dpL) {
      maxLength = Math.max(i, maxLength);
    }

    // Stores the count of LIS
    int count = 0;

    // Finding count
    for (int i = 0; i < n; i++) {
      // Update the count
      if (dpL[i] == maxLength)
        count += dpC[i];
    }

    // If count is more than 1 LIS
    // then second longest will be
    // same as length of LIS(maxLength)
    // else it will be maxLength-1
    if (count > 1) {
      return maxLength;
    }
    else {
      return maxLength - 1;
    }
  }

  public static void main(String[] args)
  {
    int arr[] = { 1, -4, 3, 5, 9 };
    int n = arr.length;
    System.out.printf(
      "Length of second longest increasing subsequence is %d\n",
      secondLis(arr, n));
  }
}
// This code is contributed by Prasad Kandekar(prasad264)

Python3

# Python code implementation: 
import sys

# Function to find the second longest increasing subsequence
def second_lis(arr, n):
    # Initialize dpL array with 1 which Store the 
    # length of the longest increasing subsequences
    dpL = [1]*n

    # Initialize dpC array with 1 which store the
    # count of the longest increasing subsequence 
    # at each index
    dpC = [1]*n

    for i in range(n):
        for j in range(i):
            # If current element is smaller
            if arr[i] <= arr[j]:
                continue

            if dpL[j] + 1 > dpL[i]:
                # If new longer lis found, update current
                # length max upto this index as dpL[j]+1,
                # and also update count of current size as 
                # that of dpC[j]th
                dpL[i] = dpL[j] + 1
                dpC[i] = dpC[j]
            elif dpL[j] + 1 == dpL[i]:
                # Else if similar length, add up ith index
                # count with jth.
                dpC[i] += dpC[j]

    # Finding length of LIS
    max_length = max(dpL)

    # Stores the count of LIS
    count = 0

    # Finding count
    for i in range(n):
        # Update the count
        if dpL[i] == max_length:
            count += dpC[i]

    # If count is more than 1 LIS then second 
    # longest will be same as length of LIS(maxLength) 
    # else it will be maxLength-1
    if count > 1:
        return max_length
    else:
        return max_length - 1


arr = [1, -4, 3, 5, 9]
n = len(arr)

print("Length of second longest increasing subsequence is", second_lis(arr, n))

# This code is contributed by sankar.

C#

// C# code for above approach
using System;

public class GFG {
  
  // Function to find the second
  // longest increasing subsequence
  public static int secondLis(int[] arr, int n)
  {
    
    // Initialize dpL array with
    // 1 which Store the length of
    // the longest increasing subsequences
    int[] dpL = new int[n];
    Array.Fill(dpL, 1);

    // Initialize dpC array with
    // 1 which store the count of
    // the longest increasing
    // subsequence at each index
    int[] dpC = new int[n];
    Array.Fill(dpC, 1);

    for (int i = 0; i < n; i++) {
      for (int j = 0; j < i; j++) {
        // If current element is
        // smaller
        if (arr[i] <= arr[j])
          continue;

        if (dpL[j] + 1 > dpL[i]) {

          // If new longer lis found,
          // update current length
          // max upto this index as
          // dpL[j]+1, and also
          // update count of current
          // size as that of dpC[j]th
          dpL[i] = dpL[j] + 1;
          dpC[i] = dpC[j];
        }
        else if (dpL[j] + 1 == dpL[i]) {
          // Else if similar length,
          // add up ith index count
          // with jth.
          dpC[i] += dpC[j];
        }
      }
    }

    // Finding length of LIS
    int maxLength = 0;
    foreach(int i in dpL)
    {
      maxLength = Math.Max(i, maxLength);
    }

    // Stores the count of LIS
    int count = 0;

    // Finding count
    for (int i = 0; i < n; i++) {
      // Update the count
      if (dpL[i] == maxLength)
        count += dpC[i];
    }

    // If count is more than 1 LIS
    // then second longest will be
    // same as length of LIS(maxLength)
    // else it will be maxLength-1
    if (count > 1) {
      return maxLength;
    }
    else {
      return maxLength - 1;
    }
  }

  // Driver Code
  static public void Main()
  {
    int[] arr = { 1, -4, 3, 5, 9 };
    int n = arr.Length;
    Console.WriteLine(
      "Length of second longest increasing subsequence is "
      + secondLis(arr, n));
  }
}

// This code is contributed by Rohit Pradhan

Javascript

// Javascript code for above approach

// Function to find the second
// longest increasing subsequence
function secondLis(arr) {
    const n = arr.length;

    // Initialize dpL array with
    // 1 which Store the length of
    // the longest increasing subsequences
    const dpL = new Array(n).fill(1);

    // Initialize dpC array with
    // 1 which store the count of
    // the longest increasing
    // subsequence at each index
    const dpC = new Array(n).fill(1);

    for (let i = 0; i < n; i++) {
        for (let j = 0; j < i; j++) {
            // If current element is
            // smaller
            if (arr[i] <= arr[j])
                continue;

            if (dpL[j] + 1 > dpL[i]) {
                // If new longer lis found,
                // update current length
                // max upto this index as
                // dpL[j]+1, and also
                // update count of current
                // size as that of dpC[j]th
                dpL[i] = dpL[j] + 1;
                dpC[i] = dpC[j];
            }
            else if (dpL[j] + 1 == dpL[i]) {

                // Else if similar length,
                // add up ith index count
                // with jth.
                dpC[i] += dpC[j];
            }
        }
    }

    // Finding length of LIS
    let maxLength = 0;
    for (let i of dpL)
        maxLength = Math.max(i, maxLength);

    // Stores the count of LIS
    let count = 0;

    // Finding count
    for (let i = 0; i < n; i++) {

        // Update the count
        if (dpL[i] == maxLength)
            count += dpC[i];
    }

    // If count is more than 1 LIS
    // then second longest will be
    // same as length of LIS(maxLength)
    // else it will be maxLength-1
    if (count > 1) {
        return maxLength;
    }
    else {
        return maxLength - 1;
    }
}

// Driver's code
const arr = [1, -4, 3, 5, 9];
console.log(`Length of second longest increasing subsequence is ${secondLis(arr)}`);
Output

Length of second longest increasing subsequence is 4

Time Complexity: O(N2)
Auxiliary Space: O(N)

Memoised Dynamic Programming Approach:

We can also solve the problem using memoised approach of dynamic programming. 

The algorithm for the implementation is as follows:

  1. Initialize the input array arr[] and its size n.
  2. Create two empty vectors dpL and dpC, each of size n, and initialize them to -1.
  3. Define a function secondLis(arr, n, dpL, dpC) to compute the length of the second longest increasing subsequence for the nth index of the input array.
    a. If dpL[n] is already calculated, return dpL[n].
    b. Otherwise, set dpL[n] and dpC[n] to 1.
    c. Iterate over all indices i less than n:
           If arr[n] is greater than arr[i]:
                 Compute the length of the second longest increasing subsequence for index i by calling secondLis(arr, i, dpL, dpC).
                 If the length of the LIS for index i plus 1 is greater than dpL[n], update dpL[n] to be len + 1 and dpC[n] to be dpC[i].
                 If the length of the LIS for index i plus 1 is equal to dpL[n], update dpC[n] to be dpC[n] + dpC[i].
    d. Return dpL[n].
  4. Define the main function:
    a. Initialize maxLength to 0 and count to 0.
    b. Iterate over all indices i from 0 to n – 1:
          i. Compute the length of the second longest increasing subsequence for index i by calling secondLis(arr, i, dpL, dpC).
          ii. If the length is greater than maxLength, update maxLength to be the length and count to be dpC[i].
          iii. If the length is equal to maxLength, update count to be count + dpC[i].
    c. If count is greater than 1, print “Length of second longest increasing subsequence is maxLength”.
    d. Otherwise, print “Length of second longest increasing subsequence is maxLength – 1”.

Below is the implementation of the algorithm:

C++

// C++ code for the approach

#include <bits/stdc++.h>
using namespace std;

// Function to find the second longest increasing subsequence
int secondLis(int arr[], int n, vector<int>& dpL, vector<int>& dpC) {
    // If dpL[i] is already calculated, return it
    if (dpL[n] != -1)
        return dpL[n];

    // Otherwise, compute dpL[i] and dpC[i] values
    dpL[n] = 1;
    dpC[n] = 1;
    for (int i = 0; i < n; i++) {
        if (arr[n] > arr[i]) {
            int len = secondLis(arr, i, dpL, dpC);
            if (len + 1 > dpL[n]) {
                dpL[n] = len + 1;
                dpC[n] = dpC[i];
            }
            else if (len + 1 == dpL[n]) {
                dpC[n] += dpC[i];
            }
        }
    }

    return dpL[n];
}

// Driver's code
int main() {
    int arr[] = { 1, -4, 3, 5, 9 };
    int n = sizeof(arr) / sizeof(arr[0]);

    // Initialize dpL and dpC arrays with -1
    vector<int> dpL(n, -1);
    vector<int> dpC(n, -1);

    // Compute dpL and dpC values for each index
    int maxLength = 0, count = 0;
    for (int i = 0; i < n; i++) {
        int len = secondLis(arr, i, dpL, dpC);
        if (len > maxLength) {
            maxLength = len;
            count = dpC[i];
        }
        else if (len == maxLength) {
            count += dpC[i];
        }
    }

    // If count is more than 1 LIS
    // then second longest will be
    // same as length of LIS(maxLength)
    // else it will be maxLength-1
    if (count > 1) {
        cout << "Length of second longest increasing subsequence is " << maxLength << endl;
    }
    else {
        cout << "Length of second longest increasing subsequence is " << maxLength - 1 << endl;
    }

    return 0;
}

Java

// Java code for the approach
import java.util.*;

class GFG 
{

  // Function to find the second longest increasing
  // subsequence
  public static int secondLis(int arr[], int n, int[] dpL,
                              int[] dpC) {
    // If dpL[i] is already calculated, return it
    if (dpL[n] != -1)
      return dpL[n];
    // Otherwise, compute dpL[i] and dpC[i] values
    dpL[n] = 1;
    dpC[n] = 1;
    for (int i = 0; i < n; i++) {
      if (arr[n] > arr[i]) {
        int len = secondLis(arr, i, dpL, dpC);
        if (len + 1 > dpL[n]) {
          dpL[n] = len + 1;
          dpC[n] = dpC[i];
        }
        else if (len + 1 == dpL[n]) {
          dpC[n] += dpC[i];
        }
      }
    }

    return dpL[n];
  }

  // Driver's code
  public static void main(String[] args) {
    int arr[] = { 1, -4, 3, 5, 9 };
    int n = arr.length;

    // Initialize dpL and dpC arrays with -1
    int[] dpL = new int[n];
    int[] dpC = new int[n];
    Arrays.fill(dpL, -1);
    Arrays.fill(dpC, -1);

    // Compute dpL and dpC values for each index
    int maxLength = 0, count = 0;
    for (int i = 0; i < n; i++) {
      int len = secondLis(arr, i, dpL, dpC);
      if (len > maxLength) {
        maxLength = len;
        count = dpC[i];
      }
      else if (len == maxLength) {
        count += dpC[i];
      }
    }

    // If count is more than 1 LIS
    // then second longest will be
    // same as length of LIS(maxLength)
    // else it will be maxLength-1
    if (count > 1) {
      System.out.println(
        "Length of second longest increasing subsequence is "
        + maxLength);
    }
    else {
      System.out.println(
        "Length of second longest increasing subsequence is "
        + (maxLength - 1));
    }
  }
}

Python3

# Python3 code for the approach

# Function to find the second longest increasing subsequence
def secondLis(arr):
  n = len(arr)
  # Initialize dpL and dpC arrays with -1
  dpL = [-1]*n
  dpC = [-1]*n
  
  # If dpL[i] is already calculated, return it
  def dp(n):
      if dpL[n] != -1:
          return dpL[n]

      # Otherwise, compute dpL[i] and dpC[i] values
      dpL[n] = 1
      dpC[n] = 1
      for i in range(n):
          if arr[n] > arr[i]:
              length = dp(i)
              if length + 1 > dpL[n]:
                  dpL[n] = length + 1
                  dpC[n] = dpC[i]
              elif length + 1 == dpL[n]:
                  dpC[n] += dpC[i]
      return dpL[n]

  # Compute dpL and dpC values for each index
  maxLength = 0
  count = 0
  for i in range(n):
      length = dp(i)
      if length > maxLength:
          maxLength = length
          count = dpC[i]
      elif length == maxLength:
          count += dpC[i]

  # If count is more than 1 LIS
  # then second longest will be
  # same as length of LIS(maxLength)
  # else it will be maxLength-1
  if count > 1:
      print("Length of second longest increasing subsequence is", maxLength)
  else:
      print("Length of second longest increasing subsequence is", maxLength-1)

# Driver's code
if __name__ == '__main__':
  # Input array
  arr = [1, -4, 3, 5, 9]
  
  # Function Call
  secondLis(arr)
  

C#

using System;

public class GFG 
{
    // Function to find the second longest increasing
    // subsequence
    public static int SecondLis(int[] arr, int n, int[] dpL, int[] dpC) 
    {
        // If dpL[i] is already calculated, return it
        if (dpL[n] != -1)
            return dpL[n];
        
        // Otherwise, compute dpL[i] and dpC[i] values
        dpL[n] = 1;
        dpC[n] = 1;
        for (int i = 0; i < n; i++) 
        {
            if (arr[n] > arr[i]) 
            {
                int len = SecondLis(arr, i, dpL, dpC);
                if (len + 1 > dpL[n]) 
                {
                    dpL[n] = len + 1;
                    dpC[n] = dpC[i];
                }
                else if (len + 1 == dpL[n]) 
                {
                    dpC[n] += dpC[i];
                }
            }
        }

        return dpL[n];
    }

    // Driver's code
    public static void Main(string[] args) 
    {
        int[] arr = { 1, -4, 3, 5, 9 };
        int n = arr.Length;

        // Initialize dpL and dpC arrays with -1
        int[] dpL = new int[n];
        int[] dpC = new int[n];
        for (int i = 0; i < n; i++) 
        {
            dpL[i] = -1;
            dpC[i] = -1;
        }

        // Compute dpL and dpC values for each index
        int maxLength = 0, count = 0;
        for (int i = 0; i < n; i++) 
        {
            int len = SecondLis(arr, i, dpL, dpC);
            if (len > maxLength) 
            {
                maxLength = len;
                count = dpC[i];
            }
            else if (len == maxLength) 
            {
                count += dpC[i];
            }
        }

        // If count is more than 1 LIS
        // then second longest will be
        // same as length of LIS(maxLength)
        // else it will be maxLength-1
        if (count > 1) 
        {
            Console.WriteLine(
                "Length of second longest increasing subsequence is " + maxLength);
        }
        else 
        {
            Console.WriteLine(
                "Length of second longest increasing subsequence is " + (maxLength - 1));
        }
    }
}

Javascript

// JavaScript code for the approach

// Function to find the second longest increasing subsequence
function secondLis(arr) {
    const n = arr.length;

    // Initialize dpL and dpC arrays with -1
    const dpL = Array(n).fill(-1);
    const dpC = Array(n).fill(-1);

    // Function to find the second longest increasing subsequence
    function secondLisHelper(n) {
        // If dpL[i] is already calculated, return it
        if (dpL[n] !== -1)
            return dpL[n];

        // Otherwise, compute dpL[i] and dpC[i] values
        dpL[n] = 1;
        dpC[n] = 1;
        for (let i = 0; i < n; i++) {
            if (arr[n] > arr[i]) {
                const len = secondLisHelper(i);
                if (len + 1 > dpL[n]) {
                    dpL[n] = len + 1;
                    dpC[n] = dpC[i];
                }
                else if (len + 1 === dpL[n]) {
                    dpC[n] += dpC[i];
                }
            }
        }

        return dpL[n];
    }

    // Compute dpL and dpC values for each index
    let maxLength = 0, count = 0;
    for (let i = 0; i < n; i++) {
        const len = secondLisHelper(i);
        if (len > maxLength) {
            maxLength = len;
            count = dpC[i];
        }
        else if (len === maxLength) {
            count += dpC[i];
        }
    }

    // If count is more than 1 LIS
    // then second longest will be
    // same as length of LIS(maxLength)
    // else it will be maxLength-1
    if (count > 1) {
        console.log(`Length of second longest increasing subsequence is ${maxLength}`);
    }
    else {
        console.log(`Length of second longest increasing subsequence is ${maxLength - 1}`);
    }
}

// Driver's code
const arr = [1, -4, 3, 5, 9];
secondLis(arr);
Output

Length of second longest increasing subsequence is 4

Time Complexity: O(n*n) where n is size of input array.
Auxiliary Space: O(n) as 1D vectors dpL and dpC are created.



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads