Longest subsequence having greater corner values
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: 4
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: 2
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 straightforward 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 #include<bits/stdc++.h> using namespace std; #define MAXN 100005 // Function to return the length of the // longest required sub-sequence int 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 code int main() { int arr[] = { 1, 2, 3, 4, 5 }; int n = sizeof (arr) / sizeof (arr[0]); cout << longestSubSeq(n, arr); } // This code is contributed by ihritik |
Java
// Java implementation of the approach 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(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-sequence def longestSubSeq(n, arr): max_length = 0 # Create a position array to find # where an element is present pos = [ 0 ] * 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 code arr = [ 1 , 2 , 3 , 4 , 5 ] n = len (arr) print (longestSubSeq(n, arr)) # This code is contributed by ihritik |
C#
// C# implementation of the approach using 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
<?php // PHP implementation of the approach $MAXN = 100005; // Function to return the length of the // longest required sub-sequence function longestSubSeq( $n , $arr ) { global $MAXN ; $max_length = 0; // Create a position array to find // where an element is present $pos = array (); for ( $i = 0; $i < $n ; $i ++) $pos [ $arr [ $i ] - 1] = $i ; $left = $n ; $right = 0; $num = 1; for ( $i = $n - 1; $i >= 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
<script> // JavaScript implementation of the approach let MAXN = 1e5 + 5; // Function to return the length of the // longest required sub-sequence function longestSubSeq(n, arr) { let max_length = 0; // Create a position array to find // where an element is present let pos = new Array(MAXN); pos.fill(0); for (let i = 0; i < n; i++) pos[arr[i] - 1] = i; let left = n, right = 0; for (let 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; } let arr = [ 1, 2, 3, 4, 5 ]; let n = arr.length; document.write(longestSubSeq(n, arr)); </script> |
2
Time Complexity: O(n), where n is the size of the given array.
Auxiliary Space: O(MAXN)
Please Login to comment...