Minimum removals required to convert given array to a Mountain Array
Last Updated :
02 Feb, 2023
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 1:
The idea is to solve this problem using the 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 the following conditions:
- The 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 the maximum, that index is the peak of the mountain array, say X.
- 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++
#include <bits/stdc++.h>
using namespace std;
int minRemovalsUtil( int arr[], int n)
{
int result = 0;
if (n < 3) {
return -1;
}
int leftIncreasing[n] = {0};
int rightIncreasing[n] = {0};
for ( int i = 1; i < n; i++)
{
for ( int j = 0; j < i; j++)
{
if (arr[j] < arr[i])
{
leftIncreasing[i]
= max(leftIncreasing[i],
leftIncreasing[j] + 1);
}
}
}
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);
}
}
}
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);
}
void minRemovals( int arr[], int n)
{
int ans = minRemovalsUtil(arr, n);
cout << ans;
}
int main()
{
int arr[] = { 2, 1, 1, 5, 6, 2, 3, 1 };
int n = sizeof (arr) / sizeof (arr[0]);
minRemovals(arr, n);
return 0;
}
|
Java
import java.io.*;
import java.util.*;
class GFG {
public static int minRemovalsUtil(
int [] arr)
{
int result = 0 ;
if (arr.length < 3 ) {
return - 1 ;
}
int [] leftIncreasing
= new int [arr.length];
int [] rightIncreasing = new int [arr.length];
for ( int i = 1 ; i < arr.length; i++) {
for ( int j = 0 ; j < i; j++) {
if (arr[j] < arr[i]) {
leftIncreasing[i]
= Math.max(
leftIncreasing[i],
leftIncreasing[j] + 1 );
}
}
}
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 );
}
}
}
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 );
}
public static void minRemovals( int [] arr)
{
int ans = minRemovalsUtil(arr);
System.out.println(ans);
}
public static void main(String[] args)
{
int [] arr = { 2 , 1 , 1 , 5 , 6 , 2 , 3 , 1 };
minRemovals(arr);
}
}
|
Python3
def minRemovalsUtil(arr):
result = 0
if ( len (arr) < 3 ):
return - 1
leftIncreasing = [ 0 ] * len (arr)
rightIncreasing = [ 0 ] * len (arr)
for i in range ( 1 , len (arr)):
for j in range (i):
if (arr[j] < arr[i]):
leftIncreasing[i] = max (leftIncreasing[i],
leftIncreasing[j] + 1 );
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
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 )
def minRemovals(arr):
ans = minRemovalsUtil(arr)
print (ans)
if __name__ = = "__main__" :
arr = [ 2 , 1 , 1 , 5 , 6 , 2 , 3 , 1 ]
minRemovals(arr)
|
C#
using System;
class GFG
{
public static int minRemovalsUtil( int [] arr)
{
int result = 0;
if (arr.Length < 3)
{
return -1;
}
int [] leftIncreasing
= new int [arr.Length];
int [] rightIncreasing = new int [arr.Length];
for ( int i = 1; i < arr.Length; i++)
{
for ( int j = 0; j < i; j++)
{
if (arr[j] < arr[i])
{
leftIncreasing[i]
= Math.Max(
leftIncreasing[i],
leftIncreasing[j] + 1);
}
}
}
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);
}
}
}
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);
}
public static void minRemovals( int [] arr)
{
int ans = minRemovalsUtil(arr);
Console.WriteLine(ans);
}
public static void Main(String[] args)
{
int [] arr = {2, 1, 1, 5, 6, 2, 3, 1};
minRemovals(arr);
}
}
|
Javascript
<script>
function minRemovalsUtil(arr, n)
{
var result = 0;
if (n < 3) {
return -1;
}
var leftIncreasing = Array(n).fill(0);
var rightIncreasing = Array(n).fill(0);
for ( var i = 1; i < n; i++)
{
for ( var j = 0; j < i; j++)
{
if (arr[j] < arr[i])
{
leftIncreasing[i]
= Math.max(leftIncreasing[i],
leftIncreasing[j] + 1);
}
}
}
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);
}
}
}
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 minRemovals(arr, n)
{
var ans = minRemovalsUtil(arr, n);
document.write( ans);
}
var arr = [2, 1, 1, 5, 6, 2, 3, 1];
var n = arr.length;
minRemovals(arr, n);
</script>
|
Time Complexity: O(N2), where N is the number of elements in the array
In the worst case every time we have to compare with all previous elements again.
Auxiliary Space: O(N)
For the left and right increasing array
Approach 2 : (Efficient Code)
The idea is same but by doing a slight change in the previous code we can reduce the redundant work.
The algorithm is basically works on finding the largest bitonic subsequence and after finding it subtract from the total length of the array. That will be the required answer. Below explanation is for the following.
We were making the left increasing and right increasing subsequence array and for each we are doing the same work twice. That can be done by a single function and reverse the result to our need., i.e. a slight observation upon the current scenario is, we basically need a longest increasing subsequence (LIS) and longest decreasing subsequence (LDS). And taking both of them in right direction.
For understanding it, if given array is [2 1 1 5 6 2 3 1] then the LIS array would look something like, [1 1 1 2 3 2 3 1] and if we would find the LDS array that would look like [2 1 1 3 3 2 2 1]. It can be easily achieved by the LIS function by passing the reversed array.
Below is the implementation of the algorithm :
C++
#include <bits/stdc++.h>
using namespace std;
vector< int > giveLIS(vector< int >& nums)
{
int n = nums.size();
vector< int > lis(n, 1);
for ( int i = 1; i < n; i++) {
int canAns = 1;
for ( int j = i - 1; j >= 0; j--) {
if (nums[j] < nums[i])
canAns = max(canAns, lis[j] + 1);
}
lis[i] = canAns;
}
return lis;
}
void minRemovals(vector< int >& nums, int n)
{
vector< int > lis = giveLIS(nums);
reverse(nums.begin(), nums.end());
vector< int > lds = giveLIS(nums);
reverse(lds.begin(), lds.end());
int maxi = 0;
for ( int i = 0; i < n; i++) {
if (lis[i] == 1 or lds[i] == 1)
continue ;
maxi = max(maxi, lis[i] + lds[i] - 1);
}
int ans = (n - maxi);
cout << ans;
}
int main()
{
vector< int > arr = { 2, 1, 1, 5, 6, 2, 3, 1 };
int n = arr.size();
minRemovals(arr, n);
return 0;
}
|
Java
import java.util.*;
import java.io.*;
class GFG{
static ArrayList<Integer> giveLIS(ArrayList<Integer> nums)
{
int n = nums.size();
ArrayList<Integer> lis = new ArrayList<Integer>();
for ( int i = 0 ; i < n ; i++){
lis.add( 1 );
}
for ( int i = 1 ; i < n ; i++) {
int canAns = 1 ;
for ( int j = i - 1 ; j >= 0 ; j--) {
if (nums.get(j) < nums.get(i))
canAns = Math.max(canAns, lis.get(j) + 1 );
}
lis.set(i, canAns);
}
return lis;
}
static void minRemovals(ArrayList<Integer> nums, int n)
{
ArrayList<Integer> lis = giveLIS(nums);
Collections.reverse(nums);
ArrayList<Integer> lds = giveLIS(nums);
Collections.reverse(lds);
int maxi = 0 ;
for ( int i = 0 ; i < n ; i++) {
if (lis.get(i) == 1 || lds.get(i) == 1 )
continue ;
maxi = Math.max(maxi, lis.get(i) + lds.get(i) - 1 );
}
int ans = (n - maxi);
System.out.println(ans);
}
public static void main(String args[])
{
ArrayList<Integer> arr = new ArrayList<Integer>(
List.of(
2 , 1 , 1 , 5 , 6 , 2 , 3 , 1
)
);
int n = arr.size();
minRemovals(arr, n);
}
}
|
Python3
from typing import List
def giveLIS(nums: List [ int ]) - > List [ int ]:
n = len (nums)
lis = [ 1 ] * n
for i in range ( 1 , n):
canAns = 1
for j in range (i - 1 , - 1 , - 1 ):
if nums[j] < nums[i]:
canAns = max (canAns, lis[j] + 1 )
lis[i] = canAns
return lis
def minRemovals(nums: List [ int ], n: int ):
lis = giveLIS(nums)
nums.reverse()
lds = giveLIS(nums)
nums.reverse()
lds.reverse()
maxi = 0
for i in range (n):
if lis[i] = = 1 or lds[i] = = 1 :
continue
maxi = max (maxi, lis[i] + lds[i] - 1 )
ans = (n - maxi)
print (ans)
arr = [ 2 , 1 , 1 , 5 , 6 , 2 , 3 , 1 ]
n = len (arr)
minRemovals(arr, n)
|
C#
using System;
using System.Collections;
using System.Collections.Generic;
class GFG
{
static List< int > giveLIS(List< int > nums)
{
int n = nums.Count;
List< int > lis = new List< int >();
for ( int i = 0 ; i < n ; i++){
lis.Add(1);
}
for ( int i = 1 ; i < n ; i++) {
int canAns = 1;
for ( int j = i - 1 ; j >= 0 ; j--) {
if (nums[j] < nums[i])
canAns = Math.Max(canAns, lis[j] + 1);
}
lis[i] = canAns;
}
return lis;
}
static void minRemovals(List< int > nums, int n)
{
List< int > lis = giveLIS(nums);
nums.Reverse();
List< int > lds = giveLIS(nums);
lds.Reverse();
int maxi = 0;
for ( int i = 0 ; i < n ; i++) {
if (lis[i] == 1 || lds[i] == 1)
continue ;
maxi = Math.Max(maxi, lis[i] + lds[i] - 1);
}
int ans = (n - maxi);
Console.WriteLine(ans);
}
public static void Main( string [] args){
List< int > arr = new List< int >{2, 1, 1, 5, 6, 2, 3, 1};
int n = arr.Count;
minRemovals(arr, n);
}
}
|
Javascript
function giveLIS(nums) {
let n = nums.length;
let lis = new Array(n).fill(1);
for (let i = 1; i < n; i++) {
let canAns = 1;
for (let j = i - 1; j >= 0; j--) {
if (nums[j] < nums[i])
canAns = Math.max(canAns, lis[j] + 1);
}
lis[i] = canAns;
}
return lis;
}
function minRemovals(nums) {
let lis = giveLIS(nums);
nums.reverse();
let lds = giveLIS(nums);
lds.reverse();
let maxi = 0;
for (let i = 0; i < nums.length; i++) {
if (lis[i] === 1 || lds[i] === 1)
continue ;
maxi = Math.max(maxi, lis[i] + lds[i] - 1);
}
let ans = (nums.length - maxi);
document.write(ans);
}
let arr = [ 2, 1, 1, 5, 6, 2, 3, 1 ];
minRemovals(arr);
|
Time Complexity: O(N^2), where N is the number of elements in the array
In the worst case every time we have to compare with all previous elements again.
Auxiliary Space: O(N)
For the LIS and LDS array we are making to calculate
Similar Reads
Minimum operations of given type required to empty given array
Given an array arr[] of size N, the task is to find the total count of operations required to remove all the array elements such that if the first element of the array is the smallest element, then remove that element, otherwise move the first element to the end of the array. Examples: Input: A[] =
14 min read
Minimum count of elements required to obtain the given Array by repeated mirror operations
Given an array arr[] consisting of N integers, the task is to find the array K[] of minimum possible length such that after performing multiple mirror operations on K[], the given array arr[] can be obtained. Mirror Operation: Appending all the array elements to the original array in reverse order.
7 min read
Minimum steps required to reduce all array elements to 1 based on given steps
Given an array arr[] of size N. The task is to find the minimum steps required to reduce all array elements to 1. In each step, perform the following given operation: Choose any starting index, say i, and jump to the (arr[i] + i)th index, reducing ith as well as (arr[i] + i)th index by 1, follow thi
8 min read
Minimum cost required to rearrange a given array to make it equal to another given array
Given two arrays A[] and B[] consisting of M and N integers respectively, and an integer C, the task is to find the minimum cost required to make the sequence A exactly the same as B(consists of distinct elements only) by performing the following operations on array A[]: Remove any element from the
12 min read
Minimum number of steps required to obtain the given Array by the given operations
Given an array arr[] of N positive integers, the task is to find the minimum number of operations required of the following types to obtain the array arr[] from an array of zeroes only. Select any index i and increment all the elements at the indices [i, N - 1] by 1.Select any index i and decrease a
12 min read
Make given Array as Mountain array by removing minimum number of elements
Given an array arr[] of length N, the task is to remove the minimum number of elements from the array to make it a mountain array and then print it. Note: A mountain array is an array where there is an index i such that arr[0] < arr[1] < . . .< arr[i-1] < arr[i] > arr[i+1] > . . .
11 min read
Minimum Subarray flips required to convert all elements of a Binary Array to K
The problem statement is asking for the minimum number of operations required to convert all the elements of a given binary array arr[] to a specified value K, where K can be either 0 or 1. The operations can be performed on any index X of the array, and the operation is to flip all the elements of
8 min read
Minimum operations required to change the array such that |arr[i] - M| <= 1
Given an array arr[] of integers, the task is to find the minimum number of operations required to change the array elements such that for any positive integer M, |arr[i] - M| ? 1 for all valid i. In a single operation, any element of the array can either be incremented or decremented by 1.Examples:
6 min read
Minimum removals required to make frequency of each array element equal to its value
Given an array arr[] of size N, the task is to find the minimum count of array elements required to be removed such that frequency of each array element is equal to its value Examples: Input: arr[] = { 2, 4, 1, 4, 2 } Output: 2 Explanation: Removing arr[1] from the array modifies arr[] to { 2, 1, 4,
11 min read
Minimum peak elements from an array by their repeated removal at every iteration of the array
Given an array arr[] consisting of N distinct positive integers, the task is to repeatedly find the minimum peak element from the given array and remove that element until all the array elements are removed. Peak Element: Any element in the array is known as the peak element based on the following c
11 min read