Open In App

Longest subsequence having greater corner values

Last Updated : 16 Nov, 2022
Comments
Improve
Suggest changes
Like Article
Like
Report

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<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
// 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
<?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
?>
JavaScript
<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>

Output: 
2

 

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


Article Tags :
Practice Tags :

Similar Reads