给定一个由N个整数组成的数组arr [] ,任务是找到要使给定数组成为山形数组所需的最少数量的数组元素。
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].
例子:
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.
方法:想法是使用自下而上的动态编程方法解决此问题。请按照以下步骤解决问题:
- 如果给定数组的长度小于3,则该数组无法转换为山峰数组。
- 否则,遍历数组,对于第i个元素(0 ,遍历子数组{arr [0],…,arr [i – 1]}中的递增子序列的长度,并将其存储在数组中,说leftIncreasing [] 。
- 同样,对于每个第i个元素(0 ,在子数组{arr [i + 1],…。,arr [N-1]}中找到递增子序列的长度,并将其存储在数组中,说出rightIncreasing []。
- 找到满足以下条件的索引i(0 :
- 第一个强制性条件是高峰条件,即leftIncreasing [i]> 0和rightIncreasing [i]> 0 。
- 在所有索引中,如果leftIncreasing [i] + rightIncreasing [i]最大,则该索引是山峰阵列的峰值,即X。
- 返回结果为N –(X + 1) ,加一以使数组索引变长。
插图:
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]).
下面是上述方法的实现:
C++
// C++ program of the above approach
#include
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
时间复杂度: O(N 2 )
辅助空间: O(N)