Longest subsequence having greater corner values

• Difficulty Level : Medium
• Last Updated : 02 Jun, 2021

Given an array arr[] containing a random permutation of first N natural numbers, the task is to find the longest sub-sequence having the property that the first and the last elements are greater than all the other sub-sequence elements.
Examples:

Input: arr[] = {3, 1, 5, 2, 4}
Output:
The sub-sequence is {3, 1, 2, 4}. The corner elements of this subsequence are greater than all other elements.
Input: arr[] = {1, 2, 3, 4, 5}
Output:
We cannot make a subsequence of size greater than 2.

Approach: If we fix the leftmost and the rightmost elements of a sub-sequence, we are interested in counting how many elements between them have a smaller value than both. A straight forward implementation of this idea has a complexity of O(N3).
In order to reduce the complexity, we approach the problem differently. Instead of fixing the ends of the sub-sequence, we fix the elements in between. The idea is that for a given X (1 ≤ X ≤ N), we want to find two elements greater or equal to X, that have between them as many elements as possible less than X. For a fixed X it’s optimal to choose the leftmost and rightmost elements ≤ X. Now we have a better O(N2) solution.
As X increases, the leftmost element can only increase, while the rightmost one can only decrease. We can use a pointer for each of them to get an amortised complexity of O(N).
Below is the implementation of the above approach:

C++

 // C++ implementation of the approach#includeusing namespace std; #define MAXN 100005 // Function to return the length of the// longest required sub-sequenceint longestSubSeq(int n, int arr []){    int max_length = 0;     // Create a position array to find    // where an element is present    int pos[MAXN];     for (int i = 0; i < n; i++)        pos[arr[i] - 1] = i;     int left = n, right = 0;     for (int i = n - 1, num = 1; i >= 0;                       i -= 1, num += 1)    {         // Store the minimum position        // to the left        left = min(left, pos[i]);         // Store the maximum position to        // the right        right = max(right, pos[i]);         // Recompute current maximum        max_length = max(max_length,                         right - left - num + 3);    }     // Edge case when there is a single    // element in the sequence    if (n == 1)        max_length = 1;     return max_length;} // Driver codeint main(){    int arr[] = { 1, 2, 3, 4, 5 };    int n = sizeof(arr) / sizeof(arr);    cout << longestSubSeq(n, arr);} // This code is contributed by ihritik

Java

 // Java implementation of the approachclass GFG {     static int MAXN = (int)1e5 + 5;     // Function to return the length of the    // longest required sub-sequence    static int longestSubSeq(int n, int[] arr)    {        int max_length = 0;         // Create a position array to find        // where an element is present        int[] pos = new int[MAXN];         for (int i = 0; i < n; i++)            pos[arr[i] - 1] = i;         int left = n, right = 0;         for (int i = n - 1, num = 1; i >= 0;                         i -= 1, num += 1) {             // Store the minimum position            // to the left            left = Math.min(left, pos[i]);             // Store the maximum position to            // the right            right = Math.max(right, pos[i]);             // Recompute current maximum            max_length = Math.max(max_length,                      right - left - num + 3);        }         // Edge case when there is a single        // element in the sequence        if (n == 1)            max_length = 1;         return max_length;    }     // Driver code    public static void main(String[] args)    {        int arr[] = { 1, 2, 3, 4, 5 };        int n = arr.length;        System.out.println(longestSubSeq(n, arr));    }}

Python3

 # Python3 implementation of the approach MAXN = 100005 # Function to return the length of the# longest required sub-sequencedef longestSubSeq(n, arr):     max_length = 0     # Create a position array to find    # where an element is present    pos =  * MAXN     for i in range (0, n):        pos[arr[i] - 1] = i     left = n    right = 0    num = 1         for i in range (n - 1, -1, -1) :         # Store the minimum position        # to the left        left = min(left, pos[i])         # Store the maximum position to        # the right        right = max(right, pos[i])         # Recompute current maximum        max_length = max(max_length,                right - left - num + 3)             num = num + 1             # Edge case when there is a single    # element in the sequence    if (n == 1) :        max_length = 1     return max_length # Driver codearr = [ 1, 2, 3, 4, 5 ]n = len(arr)print(longestSubSeq(n, arr)) # This code is contributed by ihritik

C#

 // C# implementation of the approachusing System; class GFG{     static int MAXN = (int)1e5 + 5;     // Function to return the length of the    // longest required sub-sequence    static int longestSubSeq(int n, int[] arr)    {        int max_length = 0;         // Create a position array to find        // where an element is present        int[] pos = new int[MAXN];         for (int i = 0; i < n; i++)            pos[arr[i] - 1] = i;         int left = n, right = 0;         for (int i = n - 1, num = 1; i >= 0;                        i -= 1, num += 1)        {             // Store the minimum position            // to the left            left = Math.Min(left, pos[i]);             // Store the maximum position to            // the right            right = Math.Max(right, pos[i]);             // Recompute current maximum            max_length = Math.Max(max_length,                    right - left - num + 3);        }         // Edge case when there is a single        // element in the sequence        if (n == 1)            max_length = 1;         return max_length;    }     // Driver code    public static void Main()    {        int []arr = { 1, 2, 3, 4, 5 };        int n = arr.Length;        Console.WriteLine(longestSubSeq(n, arr));    }} // This code is contributed by Ryuga

PHP

 = 0 ; \$i--, \$num++)    {                 // Store the minimum position        // to the left        \$left = min(\$left, \$pos[\$i]);         // Store the maximum position to        // the right        \$right = max(\$right, \$pos[\$i]);         // Recompute current maximum        \$max_length = max(\$max_length,                          \$right - \$left - \$num + 3);    }         // Edge case when there is a single    // element in the sequence    if (\$n == 1)        \$max_length = 1;     return \$max_length;} // Driver code\$arr = array(1, 2, 3, 4, 5);\$n = sizeof(\$arr);echo longestSubSeq(\$n, \$arr); // This code is contributed by ihritik?>

Javascript


Output:
2

My Personal Notes arrow_drop_up