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:
- If the length of the given array is less than 3, then the array cannot be converted to a mountain array.
- 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[].
- 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[].
- Find the index i (0 < i < N) which satisfies following conditions:
- First compulsory condition is the peak condition, which is leftIncreasing[i] > 0 and rightIncreasing[i] > 0.
- Among all indices, If leftIncreasing[i] + rightIncreasing[i] is maximum, that index is the peak of the mountain array, say X.
- 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. |
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.