Skip to content
Related Articles

Related Articles

Improve Article

Minimum removals required to convert given array to a Mountain Array

  • Difficulty Level : Expert
  • Last Updated : 31 May, 2021

Given an array arr[] consisting of N integers​​​, the task is to find the minimum number of array elements required to be removed to make the given array a mountain array. 

A mountain array has the following properties:

  • Length of the array ≥ 3.
  • There exists some index i (0-based indexing) with 0 < i < N – 1 such that: 
    • arr[0] < arr[1] < … < arr[i – 1] < arr[i]
    • arr[i] > arr[i + 1] > … > arr[arr.length – 1]. 

Examples:

Input: arr[] = {1, 3, 1} 
Output: 0
Explanation: The array itself is a mountain array. Therefore, no removal is required.

Input: arr[] = {2, 1, 1, 5, 6, 2, 3, 1}
Output: 3
Explanation: Removing arr[0], arr[1] and arr[5] modifies arr[] to {1, 5, 6, 3, 1}, which is a mountain array.



Approach: The idea is to solve this problem using the Bottom-Up Dynamic Programming approach. Follow the steps below to solve the problem:

  1. If the length of the given array is less than 3, then the array cannot be converted to a mountain array.
  2. Otherwise, traverse the array and for every ith element (0 < i < N), find the length of increasing subsequence in the subarrays {arr[0], …, arr[i – 1]} and store it in an array, say leftIncreasing[].
  3. Similarly, find the length of the increasing subsequence in the subarray {arr[i+1], …., arr[N-1]} for every ith element (0 < i < N), and store it in an array, say rightIncreasing[].
  4. Find the index i (0 < i < N) which satisfies the following conditions:
    1. The first compulsory condition is the peak condition, which is leftIncreasing[i] > 0 and rightIncreasing[i] > 0.
    2. Among all indices, If leftIncreasing[i] + rightIncreasing[i] is the maximum, that index is the peak of the mountain array, say X.
  5. Return the result as N – (X + 1), adding one to bring the array index to length.

Illustration:

Consider the array arr[] = {4, 3, 6, 4, 5} 
Therefore, leftIncreasing[] = {0, 0, 1, 1, 2} & rightIncreasing[] = {2, 1, 1, 0, 0}. 
There is only one index i = 2 (0-based indexing), for which leftIncreasing[2] > 0 and rightIncreasing[2] > 0. 
Therefore, X = leftIncreasing[2] + rightIncreasing[2] = 2. 
Therefore, the required answer = N – (X + 1) = 5 – (2 + 3)= 2. 
One of the possible solutions could be {4, 6, 5} i.e. removing 3 (arr[1]) and 4(arr[3]).

Below is the implementation of the above approach:

C++




// C++ program of the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Utility function to count array
// elements required to be removed
// to make array a mountain array
int minRemovalsUtil(int arr[], int n)
{
    int result = 0;
    if (n < 3) {
        return -1;
    }
 
    // Stores length of increasing
    // subsequence from [0, i-1]
    int leftIncreasing[n] = {0};
 
    // Stores length of increasing
    // subsequence from [i + 1, n - 1]
    int rightIncreasing[n] = {0};
 
    // Iterate for each position up to
    // N - 1 to find the length of subsequence
    for (int i = 1; i < n; i++)
    {
        for (int j = 0; j < i; j++)
        {
 
            // If j is less than i, then
            // i-th position has leftIncreasing[j]
            // + 1 lesser elements including itself
            if (arr[j] < arr[i])
            {
 
                // Check if it is the maximum
                // obtained so far
                leftIncreasing[i]
                    = max(leftIncreasing[i],
                          leftIncreasing[j] + 1);
            }
        }
    }
 
    // Search for increasing subsequence from right
    for (int i = n - 2; i >= 0; i--)
    {
        for (int j = n - 1; j > i; j--)
        {
            if (arr[j] < arr[i])
            {
                rightIncreasing[i]
                    = max(rightIncreasing[i],
                               rightIncreasing[j] + 1);
            }
        }
    }
 
    // Find the position following the peak
    // condition and have maximum leftIncreasing[i]
    // + rightIncreasing[i]
    for (int i = 0; i < n; i++)
    {
        if (leftIncreasing[i] != 0
            && rightIncreasing[i] != 0)
        {
            result = max(result,
                         leftIncreasing[i]
                         + rightIncreasing[i]);
        }
    }
    return n - (result + 1);
}
 
// Function to count elements to be
// removed to make array a mountain array
void minRemovals(int arr[], int n)
{
    int ans = minRemovalsUtil(arr, n);
 
    // Print the answer
    cout << ans;
}
 
// Driver Code
int main()
{
 
    // Given array
    int arr[] = { 2, 1, 1, 5, 6, 2, 3, 1 };
    int n = sizeof(arr) / sizeof(arr[0]);
       
    // Function Call
    minRemovals(arr, n);
    return 0;
}
 
// This code is contributed by Dharanendra L V

Java




// Java program of the above approach
 
import java.io.*;
import java.util.*;
 
class GFG {
 
    // Utility function to count array
    // elements required to be removed
    // to make array a mountain array
    public static int minRemovalsUtil(
        int[] arr)
    {
        int result = 0;
        if (arr.length < 3) {
            return -1;
        }
 
        // Stores length of increasing
        // subsequence from [0, i-1]
        int[] leftIncreasing
            = new int[arr.length];
 
        // Stores length of increasing
        // subsequence from [i + 1, n - 1]
        int[] rightIncreasing = new int[arr.length];
 
        // Iterate for each position up to
        // N - 1 to find the length of subsequence
        for (int i = 1; i < arr.length; i++) {
 
            for (int j = 0; j < i; j++) {
 
                // If j is less than i, then
                // i-th position has leftIncreasing[j]
                // + 1 lesser elements including itself
                if (arr[j] < arr[i]) {
 
                    // Check if it is the maximum
                    // obtained so far
                    leftIncreasing[i]
                        = Math.max(
                            leftIncreasing[i],
                            leftIncreasing[j] + 1);
                }
            }
        }
 
        // Search for increasing subsequence from right
        for (int i = arr.length - 2; i >= 0; i--) {
            for (int j = arr.length - 1; j > i; j--) {
                if (arr[j] < arr[i]) {
                    rightIncreasing[i]
                        = Math.max(rightIncreasing[i],
                                   rightIncreasing[j] + 1);
                }
            }
        }
 
        // Find the position following the peak
        // condition and have maximum leftIncreasing[i]
        // + rightIncreasing[i]
        for (int i = 0; i < arr.length; i++) {
            if (leftIncreasing[i] != 0
                && rightIncreasing[i] != 0) {
                result = Math.max(
                    result, leftIncreasing[i]
                                + rightIncreasing[i]);
            }
        }
 
        return arr.length - (result + 1);
    }
 
    // Function to count elements to be
    // removed to make array a mountain array
    public static void minRemovals(int[] arr)
    {
        int ans = minRemovalsUtil(arr);
 
        // Print the answer
        System.out.println(ans);
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        // Given array
        int[] arr = { 2, 1, 1, 5, 6, 2, 3, 1 };
 
        // Function Call
        minRemovals(arr);
    }
}

Python3




# Python3 program of the above approach
 
# Utility function to count array
# elements required to be removed
# to make array a mountain array
def minRemovalsUtil(arr):
     
    result = 0
     
    if (len(arr) < 3):
        return -1
 
    # Stores length of increasing
    # subsequence from [0, i-1]
    leftIncreasing = [0] * len(arr)
 
    # Stores length of increasing
    # subsequence from [i + 1, n - 1]
    rightIncreasing = [0] * len(arr)
 
    # Iterate for each position up to
    # N - 1 to find the length of subsequence
    for i in range(1, len(arr)):
        for j in range(i):
 
            # If j is less than i, then
            # i-th position has leftIncreasing[j]
            # + 1 lesser elements including itself
            if (arr[j] < arr[i]):
 
                # Check if it is the maximum
                # obtained so far
                leftIncreasing[i] = max(leftIncreasing[i],
                                        leftIncreasing[j] + 1);
                     
    # Search for increasing subsequence from right
    for i in range(len(arr) - 2 , -1, -1):
        j = len(arr) - 1
         
        while j > i:
            if (arr[j] < arr[i]) :
                rightIncreasing[i] = max(rightIncreasing[i],
                                         rightIncreasing[j] + 1)
                                         
            j -= 1
 
    # Find the position following the peak
    # condition and have maximum leftIncreasing[i]
    # + rightIncreasing[i]
    for i in range(len(arr)):
        if (leftIncreasing[i] != 0 and
           rightIncreasing[i] != 0):
            result = max(result, leftIncreasing[i] +
                                rightIncreasing[i]);
     
    return len(arr) - (result + 1)
 
# Function to count elements to be
# removed to make array a mountain array
def minRemovals(arr):
     
    ans = minRemovalsUtil(arr)
 
    # Print the answer
    print(ans)
 
# Driver Code
if __name__ == "__main__" :
         
    # Given array
    arr = [ 2, 1, 1, 5, 6, 2, 3, 1 ]
 
    # Function Call
    minRemovals(arr)
     
# This code is contributed by AnkThon

C#




// C# program of the above approach
using System;
 
class GFG
{
 
    // Utility function to count array
    // elements required to be removed 
    // to make array a mountain array
    public static int minRemovalsUtil(int[] arr)
    {
        int result = 0;
        if (arr.Length < 3)
        {
            return -1;
        }
 
        // Stores length of increasing
        // subsequence from [0, i-1]
        int[] leftIncreasing
            = new int[arr.Length];
 
        // Stores length of increasing
        // subsequence from [i + 1, n - 1]
        int[] rightIncreasing = new int[arr.Length];
 
        // Iterate for each position up to
        // N - 1 to find the length of subsequence
        for (int i = 1; i < arr.Length; i++)
        {
            for (int j = 0; j < i; j++)
            {
 
                // If j is less than i, then
                // i-th position has leftIncreasing[j]
                // + 1 lesser elements including itself
                if (arr[j] < arr[i])
                {
 
                    // Check if it is the maximum
                    // obtained so far
                    leftIncreasing[i]
                        = Math.Max(
                            leftIncreasing[i],
                            leftIncreasing[j] + 1);
                }
            }
        }
 
        // Search for increasing subsequence from right
        for (int i = arr.Length - 2; i >= 0; i--)
        {
            for (int j = arr.Length - 1; j > i; j--)
            {
                if (arr[j] < arr[i])
                {
                    rightIncreasing[i]
                        = Math.Max(rightIncreasing[i],
                                   rightIncreasing[j] + 1);
                }
            }
        }
 
        // Find the position following the peak
        // condition and have maximum leftIncreasing[i]
        // + rightIncreasing[i]
        for (int i = 0; i < arr.Length; i++)
        {
            if (leftIncreasing[i] != 0
                && rightIncreasing[i] != 0)
            {
                result = Math.Max(result, leftIncreasing[i]
                                + rightIncreasing[i]);
            }
        }
        return arr.Length - (result + 1);
    }
 
    // Function to count elements to be
    // removed to make array a mountain array
    public static void minRemovals(int[] arr)
    {
        int ans = minRemovalsUtil(arr);
 
        // Print the answer
        Console.WriteLine(ans);
    }
 
    // Driver Code
    public static void Main(String[] args) 
    {
        // Given array
        int[] arr = {2, 1, 1, 5, 6, 2, 3, 1};
 
        // Function Call
        minRemovals(arr);
    }
}
  
// This code is contributed by shikhasingrajput.

Javascript




<script>
 
// Javascript program of the above approach
 
// Utility function to count array
// elements required to be removed
// to make array a mountain array
function minRemovalsUtil(arr, n)
{
    var result = 0;
    if (n < 3) {
        return -1;
    }
 
    // Stores length of increasing
    // subsequence from [0, i-1]
    var leftIncreasing = Array(n).fill(0);
 
    // Stores length of increasing
    // subsequence from [i + 1, n - 1]
    var rightIncreasing = Array(n).fill(0);
 
    // Iterate for each position up to
    // N - 1 to find the length of subsequence
    for (var i = 1; i < n; i++)
    {
        for (var j = 0; j < i; j++)
        {
 
            // If j is less than i, then
            // i-th position has leftIncreasing[j]
            // + 1 lesser elements including itself
            if (arr[j] < arr[i])
            {
 
                // Check if it is the maximum
                // obtained so far
                leftIncreasing[i]
                    = Math.max(leftIncreasing[i],
                          leftIncreasing[j] + 1);
            }
        }
    }
 
    // Search for increasing subsequence from right
    for (var i = n - 2; i >= 0; i--)
    {
        for (var j = n - 1; j > i; j--)
        {
            if (arr[j] < arr[i])
            {
                rightIncreasing[i]
                    = Math.max(rightIncreasing[i],
                               rightIncreasing[j] + 1);
            }
        }
    }
 
    // Find the position following the peak
    // condition and have maximum leftIncreasing[i]
    // + rightIncreasing[i]
    for (var i = 0; i < n; i++)
    {
        if (leftIncreasing[i] != 0
            && rightIncreasing[i] != 0)
        {
            result = Math.max(result,
                         leftIncreasing[i]
                         + rightIncreasing[i]);
        }
    }
    return n - (result + 1);
}
 
// Function to count elements to be
// removed to make array a mountain array
function minRemovals(arr, n)
{
    var ans = minRemovalsUtil(arr, n);
 
    // Print the answer
    document.write( ans);
}
 
// Driver Code
// Given array
var arr = [2, 1, 1, 5, 6, 2, 3, 1];
var n = arr.length;
   
// Function Call
minRemovals(arr, n);
 
</script>
Output: 
3

 

Time Complexity: O(N2)
Auxiliary Space: O(N)

 

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.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.




My Personal Notes arrow_drop_up
Recommended Articles
Page :