Skip to content
Related Articles

Related Articles

Minimum removals required to convert given array to a Mountain Array
  • Last Updated : 15 Jan, 2021
GeeksforGeeks - Summer Carnival Banner

Given an array arr[] consisting of N integers​​​, the task is to find the minimum number of array elements required to be removed to 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 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 following conditions:
    1. 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 maximum, that index is the peak of the mountain array, say X.
  5. Return the result as N – (X + 1), adding one to bring 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, required answer = N – (X + 1) = 5 – (2 + 3)= 2. 
One of the possible solution can 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.
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.

My Personal Notes arrow_drop_up
Recommended Articles
Page :