 Open in App
Not now

# Longest subsequence having greater corner values

• Difficulty Level : Medium
• 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:
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
Related Articles