 GeeksforGeeks App
Open App Browser
Continue

# 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:
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 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``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);``    ``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

 `= 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`

Time Complexity: O(n), where n is the size of the given array.
Auxiliary Space: O(MAXN)

My Personal Notes arrow_drop_up