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++ 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 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 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# 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 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 ?> |
<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)