Longest subsequence having greater corner values
Last Updated :
16 Nov, 2022
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++
#include<bits/stdc++.h>
using namespace std;
#define MAXN 100005
int longestSubSeq( int n, int arr [])
{
int max_length = 0;
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)
{
left = min(left, pos[i]);
right = max(right, pos[i]);
max_length = max(max_length,
right - left - num + 3);
}
if (n == 1)
max_length = 1;
return max_length;
}
int main()
{
int arr[] = { 1, 2, 3, 4, 5 };
int n = sizeof (arr) / sizeof (arr[0]);
cout << longestSubSeq(n, arr);
}
|
Java
class GFG {
static int MAXN = ( int )1e5 + 5 ;
static int longestSubSeq( int n, int [] arr)
{
int max_length = 0 ;
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 ) {
left = Math.min(left, pos[i]);
right = Math.max(right, pos[i]);
max_length = Math.max(max_length,
right - left - num + 3 );
}
if (n == 1 )
max_length = 1 ;
return max_length;
}
public static void main(String[] args)
{
int arr[] = { 1 , 2 , 3 , 4 , 5 };
int n = arr.length;
System.out.println(longestSubSeq(n, arr));
}
}
|
Python3
MAXN = 100005
def longestSubSeq(n, arr):
max_length = 0
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 ) :
left = min (left, pos[i])
right = max (right, pos[i])
max_length = max (max_length,
right - left - num + 3 )
num = num + 1
if (n = = 1 ) :
max_length = 1
return max_length
arr = [ 1 , 2 , 3 , 4 , 5 ]
n = len (arr)
print (longestSubSeq(n, arr))
|
C#
using System;
class GFG
{
static int MAXN = ( int )1e5 + 5;
static int longestSubSeq( int n, int [] arr)
{
int max_length = 0;
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)
{
left = Math.Min(left, pos[i]);
right = Math.Max(right, pos[i]);
max_length = Math.Max(max_length,
right - left - num + 3);
}
if (n == 1)
max_length = 1;
return max_length;
}
public static void Main()
{
int []arr = { 1, 2, 3, 4, 5 };
int n = arr.Length;
Console.WriteLine(longestSubSeq(n, arr));
}
}
|
PHP
<?php
$MAXN = 100005;
function longestSubSeq( $n , $arr )
{
global $MAXN ;
$max_length = 0;
$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 ++)
{
$left = min( $left , $pos [ $i ]);
$right = max( $right , $pos [ $i ]);
$max_length = max( $max_length ,
$right - $left - $num + 3);
}
if ( $n == 1)
$max_length = 1;
return $max_length ;
}
$arr = array (1, 2, 3, 4, 5);
$n = sizeof( $arr );
echo longestSubSeq( $n , $arr );
?>
|
Javascript
<script>
let MAXN = 1e5 + 5;
function longestSubSeq(n, arr)
{
let max_length = 0;
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)
{
left = Math.min(left, pos[i]);
right = Math.max(right, pos[i]);
max_length = Math.max(max_length,
right - left - num + 3);
}
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>
|
Time Complexity: O(n), where n is the size of the given array.
Auxiliary Space: O(MAXN)
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...