Related Articles
Longest subsequence having greater corner values
• Difficulty Level : Medium
• Last Updated : 13 Mar, 2019

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.

## Recommended: Please try your approach on {IDE} first, before moving on to the solution.

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 straight forward 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``?>`
Output:
```2
```

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.

My Personal Notes arrow_drop_up