给定一个未排序的数组,修剪数组,使得修剪后的数组中最小值的两倍大于最大值。元素应从数组的任一端删除。
移除次数应最少。
例子:
arr[] = {4, 5, 100, 9, 10, 11, 12, 15, 200}
Output: 4
We need to remove 4 elements (4, 5, 100, 200)
so that 2*min becomes more than max.
arr[] = {4, 7, 5, 6}
Output: 0
We don't need to remove any element as
4*2 > 7 (Note that min = 4, max = 8)
arr[] = {20, 7, 5, 6}
Output: 1
We need to remove 20 so that 2*min becomes
more than max
arr[] = {20, 4, 1, 3}
Output: 3
We need to remove any three elements from ends
like 20, 4, 1 or 4, 1, 3 or 20, 3, 1 or 20, 4, 1
我们强烈建议您在继续解决方案之前单击此处进行练习。
天真的解决方案:
一个天真的解决方案是使用递归来尝试所有可能的情况。以下是朴素的递归算法。请注意,该算法仅返回要进行的最小删除次数,它不会打印修剪后的数组。也可以轻松修改以打印修剪后的数组。
// Returns minimum number of removals to be made in
// arr[l..h]
minRemovals(int arr[], int l, int h)
1) Find min and max in arr[l..h]
2) If 2*min > max, then return 0.
3) Else return minimum of "minRemovals(arr, l+1, h) + 1"
and "minRemovals(arr, l, h-1) + 1"
下面是上述算法的实现。
C++
// C++ implementation of above approach
#include
using namespace std;
// A utility function to find minimum of two numbers
int min(int a, int b) {return (a < b)? a : b;}
// A utility function to find minimum in arr[l..h]
int min(int arr[], int l, int h)
{
int mn = arr[l];
for (int i=l+1; i<=h; i++)
if (mn > arr[i])
mn = arr[i];
return mn;
}
// A utility function to find maximum in arr[l..h]
int max(int arr[], int l, int h)
{
int mx = arr[l];
for (int i=l+1; i<=h; i++)
if (mx < arr[i])
mx = arr[i];
return mx;
}
// Returns the minimum number of removals from either end
// in arr[l..h] so that 2*min becomes greater than max.
int minRemovals(int arr[], int l, int h)
{
// If there is 1 or less elements, return 0
// For a single element, 2*min > max
// (Assumption: All elements are positive in arr[])
if (l >= h) return 0;
// 1) Find minimum and maximum in arr[l..h]
int mn = min(arr, l, h);
int mx = max(arr, l, h);
//If the property is followed, no removals needed
if (2*mn > mx)
return 0;
// Otherwise remove a character from left end and recur,
// then remove a character from right end and recur, take
// the minimum of two is returned
return min(minRemovals(arr, l+1, h),
minRemovals(arr, l, h-1)) + 1;
}
// Driver program to test above functions
int main()
{
int arr[] = {4, 5, 100, 9, 10, 11, 12, 15, 200};
int n = sizeof(arr)/sizeof(arr[0]);
cout << minRemovals(arr, 0, n-1);
return 0;
}
Java
// Java implementation of above approach
class GFG
{
// A utility function to find minimum of two numbers
static int min(int a, int b) {return (a < b)? a : b;}
// A utility function to find minimum in arr[l..h]
static int min(int arr[], int l, int h)
{
int mn = arr[l];
for (int i=l+1; i<=h; i++)
if (mn > arr[i])
mn = arr[i];
return mn;
}
// A utility function to find maximum in arr[l..h]
static int max(int arr[], int l, int h)
{
int mx = arr[l];
for (int i=l+1; i<=h; i++)
if (mx < arr[i])
mx = arr[i];
return mx;
}
// Returns the minimum number of removals from either end
// in arr[l..h] so that 2*min becomes greater than max.
static int minRemovals(int arr[], int l, int h)
{
// If there is 1 or less elements, return 0
// For a single element, 2*min > max
// (Assumption: All elements are positive in arr[])
if (l >= h) return 0;
// 1) Find minimum and maximum in arr[l..h]
int mn = min(arr, l, h);
int mx = max(arr, l, h);
//If the property is followed, no removals needed
if (2*mn > mx)
return 0;
// Otherwise remove a character from left end and recur,
// then remove a character from right end and recur, take
// the minimum of two is returned
return min(minRemovals(arr, l+1, h),
minRemovals(arr, l, h-1)) + 1;
}
// Driver Code
public static void main(String[] args)
{
int arr[] = {4, 5, 100, 9, 10, 11, 12, 15, 200};
int n = arr.length;
System.out.print(minRemovals(arr, 0, n-1));
}
}
// This code is contributed by Mukul Singh.
Python3
# Python3 implementation of above approach
# A utility function to find
# minimum in arr[l..h]
def mini(arr, l, h):
mn = arr[l]
for i in range(l + 1, h + 1):
if (mn > arr[i]):
mn = arr[i]
return mn
# A utility function to find
# maximum in arr[l..h]
def max(arr, l, h):
mx = arr[l]
for i in range(l + 1, h + 1):
if (mx < arr[i]):
mx = arr[i]
return mx
# Returns the minimum number of
# removals from either end in
# arr[l..h] so that 2*min becomes
# greater than max.
def minRemovals(arr, l, h):
# If there is 1 or less elements, return 0
# For a single element, 2*min > max
# (Assumption: All elements are positive in arr[])
if (l >= h):
return 0
# 1) Find minimum and maximum
# in arr[l..h]
mn = mini(arr, l, h)
mx = max(arr, l, h)
# If the property is followed,
# no removals needed
if (2 * mn > mx):
return 0
# Otherwise remove a character from
# left end and recur, then remove a
# character from right end and recur,
# take the minimum of two is returned
return (min(minRemovals(arr, l + 1, h),
minRemovals(arr, l, h - 1)) + 1)
# Driver Code
arr = [4, 5, 100, 9, 10,
11, 12, 15, 200]
n = len(arr)
print(minRemovals(arr, 0, n - 1))
# This code is contributed
# by sahilshelangia
C#
// C# implementation of above approach
using System;
class GFG
{
// A utility function to find minimum of two numbers
static int min(int a, int b) {return (a < b)? a : b;}
// A utility function to find minimum in arr[l..h]
static int min(int[] arr, int l, int h)
{
int mn = arr[l];
for (int i=l+1; i<=h; i++)
if (mn > arr[i])
mn = arr[i];
return mn;
}
// A utility function to find maximum in arr[l..h]
static int max(int[] arr, int l, int h)
{
int mx = arr[l];
for (int i=l+1; i<=h; i++)
if (mx < arr[i])
mx = arr[i];
return mx;
}
// Returns the minimum number of removals from either end
// in arr[l..h] so that 2*min becomes greater than max.
static int minRemovals(int[] arr, int l, int h)
{
// If there is 1 or less elements, return 0
// For a single element, 2*min > max
// (Assumption: All elements are positive in arr[])
if (l >= h) return 0;
// 1) Find minimum and maximum in arr[l..h]
int mn = min(arr, l, h);
int mx = max(arr, l, h);
//If the property is followed, no removals needed
if (2*mn > mx)
return 0;
// Otherwise remove a character from left end and recur,
// then remove a character from right end and recur, take
// the minimum of two is returned
return min(minRemovals(arr, l+1, h),
minRemovals(arr, l, h-1)) + 1;
}
// Driver Code
public static void Main()
{
int[] arr = {4, 5, 100, 9, 10, 11, 12, 15, 200};
int n = arr.Length;
Console.Write(minRemovals(arr, 0, n-1));
}
}
// This code is contributed by Akanksha Rai
PHP
$arr[$i])
$mn = $arr[$i];
return $mn;
}
// A utility function to find
// maximum in arr[l..h]
function max_1(&$arr, $l, $h)
{
$mx = $arr[$l];
for ($i = $l + 1; $i <= $h; $i++)
if ($mx < $arr[$i])
$mx = $arr[$i];
return $mx;
}
// Returns the minimum number of removals
// from either end in arr[l..h] so that
// 2*min becomes greater than max.
function minRemovals(&$arr, $l, $h)
{
// If there is 1 or less elements,
// return 0. For a single element,
// 2*min > max. (Assumption: All
// elements are positive in arr[])
if ($l >= $h) return 0;
// 1) Find minimum and maximum in arr[l..h]
$mn = min_1($arr, $l, $h);
$mx = max_1($arr, $l, $h);
// If the property is followed,
// no removals needed
if (2 * $mn > $mx)
return 0;
// Otherwise remove a character from left
// end and recur, then remove a character
// from right end and recur, take the
// minimum of two is returned
return min(minRemovals($arr, $l + 1, $h),
minRemovals($arr, $l, $h - 1)) + 1;
}
// Driver Code
$arr = array(4, 5, 100, 9, 10,
11, 12, 15, 200);
$n = sizeof($arr);
echo minRemovals($arr, 0, $n - 1);
// This code is contributed
// by ChitraNayal
?>
Javascript
C++
// C++ program of above approach
#include
using namespace std;
// A utility function to find minimum of two numbers
int min(int a, int b) {return (a < b)? a : b;}
// A utility function to find minimum in arr[l..h]
int min(int arr[], int l, int h)
{
int mn = arr[l];
for (int i=l+1; i<=h; i++)
if (mn > arr[i])
mn = arr[i];
return mn;
}
// A utility function to find maximum in arr[l..h]
int max(int arr[], int l, int h)
{
int mx = arr[l];
for (int i=l+1; i<=h; i++)
if (mx < arr[i])
mx = arr[i];
return mx;
}
// Returns the minimum number of removals from either end
// in arr[l..h] so that 2*min becomes greater than max.
int minRemovalsDP(int arr[], int n)
{
// Create a table to store solutions of subproblems
int table[n][n], gap, i, j, mn, mx;
// Fill table using above recursive formula. Note that the table
// is filled in diagonal fashion (similar to http://goo.gl/PQqoS),
// from diagonal elements to table[0][n-1] which is the result.
for (gap = 0; gap < n; ++gap)
{
for (i = 0, j = gap; j < n; ++i, ++j)
{
mn = min(arr, i, j);
mx = max(arr, i, j);
table[i][j] = (2*mn > mx)? 0: min(table[i][j-1]+1,
table[i+1][j]+1);
}
}
return table[0][n-1];
}
// Driver program to test above functions
int main()
{
int arr[] = {20, 4, 1, 3};
int n = sizeof(arr)/sizeof(arr[0]);
cout << minRemovalsDP(arr, n);
return 0;
}
Java
// Java program of above approach
class GFG {
// A utility function to find minimum of two numbers
static int min(int a, int b) {
return (a < b) ? a : b;
}
// A utility function to find minimum in arr[l..h]
static int min(int arr[], int l, int h) {
int mn = arr[l];
for (int i = l + 1; i <= h; i++) {
if (mn > arr[i]) {
mn = arr[i];
}
}
return mn;
}
// A utility function to find maximum in arr[l..h]
static int max(int arr[], int l, int h) {
int mx = arr[l];
for (int i = l + 1; i <= h; i++) {
if (mx < arr[i]) {
mx = arr[i];
}
}
return mx;
}
// Returns the minimum number of removals from either end
// in arr[l..h] so that 2*min becomes greater than max.
static int minRemovalsDP(int arr[], int n) {
// Create a table to store solutions of subproblems
int table[][] = new int[n][n], gap, i, j, mn, mx;
// Fill table using above recursive formula. Note that the table
// is filled in diagonal fashion (similar to http://goo.gl/PQqoS),
// from diagonal elements to table[0][n-1] which is the result.
for (gap = 0; gap < n; ++gap) {
for (i = 0, j = gap; j < n; ++i, ++j) {
mn = min(arr, i, j);
mx = max(arr, i, j);
table[i][j] = (2 * mn > mx) ? 0 : min(table[i][j - 1] + 1,
table[i + 1][j] + 1);
}
}
return table[0][n - 1];
}
// Driver program to test above functions
public static void main(String[] args) {
int arr[] = {20, 4, 1, 3};
int n = arr.length;
System.out.println(minRemovalsDP(arr, n));
}
}
// This code contributed by 29AJayKumar
Python3
# Python3 program of above approach
# A utility function to find
# minimum in arr[l..h]
def min1(arr, l, h):
mn = arr[l];
for i in range(l + 1,h+1):
if (mn > arr[i]):
mn = arr[i];
return mn;
# A utility function to find
# maximum in arr[l..h]
def max1(arr, l, h):
mx = arr[l];
for i in range(l + 1, h + 1):
if (mx < arr[i]):
mx = arr[i];
return mx;
# Returns the minimum number of removals
# from either end in arr[l..h] so that
# 2*min becomes greater than max.
def minRemovalsDP(arr, n):
# Create a table to store
# solutions of subproblems
table = [[0 for x in range(n)] for y in range(n)];
# Fill table using above recursive formula.
# Note that the table is filled in diagonal fashion
# (similar to http:#goo.gl/PQqoS), from diagonal elements
# to table[0][n-1] which is the result.
for gap in range(n):
i = 0;
for j in range(gap,n):
mn = min1(arr, i, j);
mx = max1(arr, i, j);
table[i][j] = 0 if (2 * mn > mx) else min(table[i][j - 1] + 1,table[i + 1][j] + 1);
i += 1;
return table[0][n - 1];
# Driver Code
arr = [20, 4, 1, 3];
n = len(arr);
print(minRemovalsDP(arr, n));
# This code is contributed by mits
C#
// C# program of above approach
using System;
public class GFG {
// A utility function to find minimum of two numbers
static int min(int a, int b) {
return (a < b) ? a : b;
}
// A utility function to find minimum in arr[l..h]
static int min(int []arr, int l, int h) {
int mn = arr[l];
for (int i = l + 1; i <= h; i++) {
if (mn > arr[i]) {
mn = arr[i];
}
}
return mn;
}
// A utility function to find maximum in arr[l..h]
static int max(int []arr, int l, int h) {
int mx = arr[l];
for (int i = l + 1; i <= h; i++) {
if (mx < arr[i]) {
mx = arr[i];
}
}
return mx;
}
// Returns the minimum number of removals from either end
// in arr[l..h] so that 2*min becomes greater than max.
static int minRemovalsDP(int []arr, int n) {
// Create a table to store solutions of subproblems
int [,]table = new int[n,n];
int gap, i, j, mn, mx;
// Fill table using above recursive formula. Note that the table
// is filled in diagonal fashion (similar to http://goo.gl/PQqoS),
// from diagonal elements to table[0][n-1] which is the result.
for (gap = 0; gap < n; ++gap) {
for (i = 0, j = gap; j < n; ++i, ++j) {
mn = min(arr, i, j);
mx = max(arr, i, j);
table[i,j] = (2 * mn > mx) ? 0 : min(table[i,j - 1] + 1,
table[i + 1,j] + 1);
}
}
return table[0,n - 1];
}
// Driver program to test above functions
public static void Main() {
int []arr = {20, 4, 1, 3};
int n = arr.Length;
Console.WriteLine(minRemovalsDP(arr, n));
}
}
// This code contributed by 29AJayKumar
PHP
$arr[$i])
$mn = $arr[$i];
return $mn;
}
// A utility function to find
// maximum in arr[l..h]
function max1($arr, $l, $h)
{
$mx = $arr[$l];
for ($i = $l + 1; $i <= $h; $i++)
if ($mx < $arr[$i])
$mx = $arr[$i];
return $mx;
}
// Returns the minimum number of removals
// from either end in arr[l..h] so that
// 2*min becomes greater than max.
function minRemovalsDP($arr, $n)
{
// Create a table to store
// solutions of subproblems
$table = array_fill(0, $n,
array_fill(0, $n, 0));
// Fill table using above recursive formula.
// Note that the table is filled in diagonal fashion
// (similar to http://goo.gl/PQqoS), from diagonal elements
// to table[0][n-1] which is the result.
for ($gap = 0; $gap < $n; ++$gap)
{
for ($i = 0, $j = $gap; $j < $n; ++$i, ++$j)
{
$mn = min1($arr, $i, $j);
$mx = max1($arr, $i, $j);
$table[$i][$j] = (2 * $mn > $mx) ? 0 :
min($table[$i][$j - 1] + 1,
$table[$i + 1][$j] + 1);
}
}
return $table[0][$n - 1];
}
// Driver Code
$arr = array(20, 4, 1, 3);
$n = count($arr);
echo minRemovalsDP($arr, $n);
// This code is contributed by mits
?>
Javascript
C++
// A O(n*n) solution to find the minimum of elements to
// be removed
#include
#include
using namespace std;
// Returns the minimum number of removals from either end
// in arr[l..h] so that 2*min becomes greater than max.
int minRemovalsDP(int arr[], int n)
{
// Initialize starting and ending indexes of the maximum
// sized subarray with property 2*min > max
int longest_start = -1, longest_end = 0;
// Choose different elements as starting point
for (int start=0; start max) max = val;
// If the property is violated, then no
// point to continue for a bigger array
if (2 * min <= max) break;
// Update longest_start and longest_end if needed
if (end - start > longest_end - longest_start ||
longest_start == -1)
{
longest_start = start;
longest_end = end;
}
}
}
// If not even a single element follow the property,
// then return n
if (longest_start == -1) return n;
// Return the number of elements to be removed
return (n - (longest_end - longest_start + 1));
}
// Driver program to test above functions
int main()
{
int arr[] = {4, 5, 100, 9, 10, 11, 12, 15, 200};
int n = sizeof(arr)/sizeof(arr[0]);
cout << minRemovalsDP(arr, n);
return 0;
}
Java
// A O(n*n) solution to find the minimum of elements to
// be removed
class GFG {
// Returns the minimum number of removals from either end
// in arr[l..h] so that 2*min becomes greater than max.
static int minRemovalsDP(int arr[], int n) {
// Initialize starting and ending indexes of the maximum
// sized subarray with property 2*min > max
int longest_start = -1, longest_end = 0;
// Choose different elements as starting point
for (int start = 0; start < n; start++) {
// Initialize min and max for the current start
int min = Integer.MAX_VALUE, max = Integer.MIN_VALUE;
// Choose different ending points for current start
for (int end = start; end < n; end++) {
// Update min and max if necessary
int val = arr[end];
if (val < min) {
min = val;
}
if (val > max) {
max = val;
}
// If the property is violated, then no
// point to continue for a bigger array
if (2 * min <= max) {
break;
}
// Update longest_start and longest_end if needed
if (end - start > longest_end - longest_start
|| longest_start == -1) {
longest_start = start;
longest_end = end;
}
}
}
// If not even a single element follow the property,
// then return n
if (longest_start == -1) {
return n;
}
// Return the number of elements to be removed
return (n - (longest_end - longest_start + 1));
}
// Driver program to test above functions
public static void main(String[] args) {
int arr[] = {4, 5, 100, 9, 10, 11, 12, 15, 200};
int n = arr.length;
System.out.println(minRemovalsDP(arr, n));
}
}
// This code is contributed by PrinciRaj1992
Python3
# A O(n*n) solution to find the minimum of
# elements to be removed
import sys;
# Returns the minimum number of removals
# from either end in arr[l..h] so that
# 2*min becomes greater than max.
def minRemovalsDP(arr, n):
# Initialize starting and ending indexes
# of the maximum sized subarray
# with property 2*min > max
longest_start = -1;
longest_end = 0;
# Choose different elements as starting point
for start in range(n):
# Initialize min and max
# for the current start
min = sys.maxsize;
max = -sys.maxsize;
# Choose different ending points for current start
for end in range(start,n):
# Update min and max if necessary
val = arr[end];
if (val < min):
min = val;
if (val > max):
max = val;
# If the property is violated, then no
# point to continue for a bigger array
if (2 * min <= max):
break;
# Update longest_start and longest_end if needed
if (end - start > longest_end - longest_start or longest_start == -1):
longest_start = start;
longest_end = end;
# If not even a single element follow the property,
# then return n
if (longest_start == -1):
return n;
# Return the number of elements to be removed
return (n - (longest_end - longest_start + 1));
# Driver Code
arr = [4, 5, 100, 9, 10, 11, 12, 15, 200];
n = len(arr);
print(minRemovalsDP(arr, n));
# This code is contributed by mits
C#
// A O(n*n) solution to find the minimum of elements to
// be removed
using System;
public class GFG {
// Returns the minimum number of removals from either end
// in arr[l..h] so that 2*min becomes greater than max.
static int minRemovalsDP(int []arr, int n) {
// Initialize starting and ending indexes of the maximum
// sized subarray with property 2*min > max
int longest_start = -1, longest_end = 0;
// Choose different elements as starting point
for (int start = 0; start < n; start++) {
// Initialize min and max for the current start
int min = int.MaxValue, max = int.MinValue;
// Choose different ending points for current start
for (int end = start; end < n; end++) {
// Update min and max if necessary
int val = arr[end];
if (val < min) {
min = val;
}
if (val > max) {
max = val;
}
// If the property is violated, then no
// point to continue for a bigger array
if (2 * min <= max) {
break;
}
// Update longest_start and longest_end if needed
if (end - start > longest_end - longest_start
|| longest_start == -1) {
longest_start = start;
longest_end = end;
}
}
}
// If not even a single element follow the property,
// then return n
if (longest_start == -1) {
return n;
}
// Return the number of elements to be removed
return (n - (longest_end - longest_start + 1));
}
// Driver program to test above functions
public static void Main() {
int []arr = {4, 5, 100, 9, 10, 11, 12, 15, 200};
int n = arr.Length;
Console.WriteLine(minRemovalsDP(arr, n));
}
}
// This code is contributed by Rajput-Ji
PHP
max
$longest_start = -1;
$longest_end = 0;
// Choose different elements as starting point
for ($start = 0; $start < $n; $start++)
{
// Initialize min and max
// for the current start
$min = PHP_INT_MAX;
$max = PHP_INT_MIN;
// Choose different ending points for current start
for ($end = $start; $end < $n; $end ++)
{
// Update min and max if necessary
$val = $arr[$end];
if ($val < $min) $min = $val;
if ($val > $max) $max = $val;
// If the property is violated, then no
// point to continue for a bigger array
if (2 * $min <= $max) break;
// Update longest_start and longest_end if needed
if ($end - $start > $longest_end - $longest_start ||
$longest_start == -1)
{
$longest_start = $start;
$longest_end = $end;
}
}
}
// If not even a single element follow the property,
// then return n
if ($longest_start == -1) return $n;
// Return the number of elements to be removed
return ($n - ($longest_end - $longest_start + 1));
}
// Driver Code
$arr = array(4, 5, 100, 9, 10, 11, 12, 15, 200);
$n = sizeof($arr);
echo minRemovalsDP($arr, $n);
// This code is contributed by jit_t
?>
Javascript
输出:
4
时间复杂度:上述函数的时间复杂度可以写成如下
T(n) = 2T(n-1) + O(n)
上述递归解的上限是 O(nx 2 n )。
动态规划:
上面的递归代码展示了许多重叠的子问题。例如 minRemovals(arr, l+1, h-1) 被评估两次。所以动态规划是优化解的选择。以下是基于动态规划的解决方案。
C++
// C++ program of above approach
#include
using namespace std;
// A utility function to find minimum of two numbers
int min(int a, int b) {return (a < b)? a : b;}
// A utility function to find minimum in arr[l..h]
int min(int arr[], int l, int h)
{
int mn = arr[l];
for (int i=l+1; i<=h; i++)
if (mn > arr[i])
mn = arr[i];
return mn;
}
// A utility function to find maximum in arr[l..h]
int max(int arr[], int l, int h)
{
int mx = arr[l];
for (int i=l+1; i<=h; i++)
if (mx < arr[i])
mx = arr[i];
return mx;
}
// Returns the minimum number of removals from either end
// in arr[l..h] so that 2*min becomes greater than max.
int minRemovalsDP(int arr[], int n)
{
// Create a table to store solutions of subproblems
int table[n][n], gap, i, j, mn, mx;
// Fill table using above recursive formula. Note that the table
// is filled in diagonal fashion (similar to http://goo.gl/PQqoS),
// from diagonal elements to table[0][n-1] which is the result.
for (gap = 0; gap < n; ++gap)
{
for (i = 0, j = gap; j < n; ++i, ++j)
{
mn = min(arr, i, j);
mx = max(arr, i, j);
table[i][j] = (2*mn > mx)? 0: min(table[i][j-1]+1,
table[i+1][j]+1);
}
}
return table[0][n-1];
}
// Driver program to test above functions
int main()
{
int arr[] = {20, 4, 1, 3};
int n = sizeof(arr)/sizeof(arr[0]);
cout << minRemovalsDP(arr, n);
return 0;
}
Java
// Java program of above approach
class GFG {
// A utility function to find minimum of two numbers
static int min(int a, int b) {
return (a < b) ? a : b;
}
// A utility function to find minimum in arr[l..h]
static int min(int arr[], int l, int h) {
int mn = arr[l];
for (int i = l + 1; i <= h; i++) {
if (mn > arr[i]) {
mn = arr[i];
}
}
return mn;
}
// A utility function to find maximum in arr[l..h]
static int max(int arr[], int l, int h) {
int mx = arr[l];
for (int i = l + 1; i <= h; i++) {
if (mx < arr[i]) {
mx = arr[i];
}
}
return mx;
}
// Returns the minimum number of removals from either end
// in arr[l..h] so that 2*min becomes greater than max.
static int minRemovalsDP(int arr[], int n) {
// Create a table to store solutions of subproblems
int table[][] = new int[n][n], gap, i, j, mn, mx;
// Fill table using above recursive formula. Note that the table
// is filled in diagonal fashion (similar to http://goo.gl/PQqoS),
// from diagonal elements to table[0][n-1] which is the result.
for (gap = 0; gap < n; ++gap) {
for (i = 0, j = gap; j < n; ++i, ++j) {
mn = min(arr, i, j);
mx = max(arr, i, j);
table[i][j] = (2 * mn > mx) ? 0 : min(table[i][j - 1] + 1,
table[i + 1][j] + 1);
}
}
return table[0][n - 1];
}
// Driver program to test above functions
public static void main(String[] args) {
int arr[] = {20, 4, 1, 3};
int n = arr.length;
System.out.println(minRemovalsDP(arr, n));
}
}
// This code contributed by 29AJayKumar
蟒蛇3
# Python3 program of above approach
# A utility function to find
# minimum in arr[l..h]
def min1(arr, l, h):
mn = arr[l];
for i in range(l + 1,h+1):
if (mn > arr[i]):
mn = arr[i];
return mn;
# A utility function to find
# maximum in arr[l..h]
def max1(arr, l, h):
mx = arr[l];
for i in range(l + 1, h + 1):
if (mx < arr[i]):
mx = arr[i];
return mx;
# Returns the minimum number of removals
# from either end in arr[l..h] so that
# 2*min becomes greater than max.
def minRemovalsDP(arr, n):
# Create a table to store
# solutions of subproblems
table = [[0 for x in range(n)] for y in range(n)];
# Fill table using above recursive formula.
# Note that the table is filled in diagonal fashion
# (similar to http:#goo.gl/PQqoS), from diagonal elements
# to table[0][n-1] which is the result.
for gap in range(n):
i = 0;
for j in range(gap,n):
mn = min1(arr, i, j);
mx = max1(arr, i, j);
table[i][j] = 0 if (2 * mn > mx) else min(table[i][j - 1] + 1,table[i + 1][j] + 1);
i += 1;
return table[0][n - 1];
# Driver Code
arr = [20, 4, 1, 3];
n = len(arr);
print(minRemovalsDP(arr, n));
# This code is contributed by mits
C#
// C# program of above approach
using System;
public class GFG {
// A utility function to find minimum of two numbers
static int min(int a, int b) {
return (a < b) ? a : b;
}
// A utility function to find minimum in arr[l..h]
static int min(int []arr, int l, int h) {
int mn = arr[l];
for (int i = l + 1; i <= h; i++) {
if (mn > arr[i]) {
mn = arr[i];
}
}
return mn;
}
// A utility function to find maximum in arr[l..h]
static int max(int []arr, int l, int h) {
int mx = arr[l];
for (int i = l + 1; i <= h; i++) {
if (mx < arr[i]) {
mx = arr[i];
}
}
return mx;
}
// Returns the minimum number of removals from either end
// in arr[l..h] so that 2*min becomes greater than max.
static int minRemovalsDP(int []arr, int n) {
// Create a table to store solutions of subproblems
int [,]table = new int[n,n];
int gap, i, j, mn, mx;
// Fill table using above recursive formula. Note that the table
// is filled in diagonal fashion (similar to http://goo.gl/PQqoS),
// from diagonal elements to table[0][n-1] which is the result.
for (gap = 0; gap < n; ++gap) {
for (i = 0, j = gap; j < n; ++i, ++j) {
mn = min(arr, i, j);
mx = max(arr, i, j);
table[i,j] = (2 * mn > mx) ? 0 : min(table[i,j - 1] + 1,
table[i + 1,j] + 1);
}
}
return table[0,n - 1];
}
// Driver program to test above functions
public static void Main() {
int []arr = {20, 4, 1, 3};
int n = arr.Length;
Console.WriteLine(minRemovalsDP(arr, n));
}
}
// This code contributed by 29AJayKumar
PHP
$arr[$i])
$mn = $arr[$i];
return $mn;
}
// A utility function to find
// maximum in arr[l..h]
function max1($arr, $l, $h)
{
$mx = $arr[$l];
for ($i = $l + 1; $i <= $h; $i++)
if ($mx < $arr[$i])
$mx = $arr[$i];
return $mx;
}
// Returns the minimum number of removals
// from either end in arr[l..h] so that
// 2*min becomes greater than max.
function minRemovalsDP($arr, $n)
{
// Create a table to store
// solutions of subproblems
$table = array_fill(0, $n,
array_fill(0, $n, 0));
// Fill table using above recursive formula.
// Note that the table is filled in diagonal fashion
// (similar to http://goo.gl/PQqoS), from diagonal elements
// to table[0][n-1] which is the result.
for ($gap = 0; $gap < $n; ++$gap)
{
for ($i = 0, $j = $gap; $j < $n; ++$i, ++$j)
{
$mn = min1($arr, $i, $j);
$mx = max1($arr, $i, $j);
$table[$i][$j] = (2 * $mn > $mx) ? 0 :
min($table[$i][$j - 1] + 1,
$table[$i + 1][$j] + 1);
}
}
return $table[0][$n - 1];
}
// Driver Code
$arr = array(20, 4, 1, 3);
$n = count($arr);
echo minRemovalsDP($arr, $n);
// This code is contributed by mits
?>
Javascript
输出:
3
时间复杂度: O(n 3 ),其中 n 是 arr[] 中的元素数。
进一步优化:
上面的代码可以通过多种方式进行优化。
1)当 min 和/或 max 没有改变时,我们可以通过删除角元素来避免计算 min() 和/或 max()。
2)我们可以在 O(n) 时间内对数组进行预处理并构建段树。建立段树后,我们可以在 O(Logn) 时间内查询范围最小值和最大值。总时间复杂度降低到 O(n 2 Logn) 时间。
AO(n^2) 解
这个想法是找到最大尺寸的子数组,使得 2*min > max。我们运行两个嵌套循环,外循环选择一个起点,内循环选择当前起点的终点。我们跟踪具有给定属性的最长子数组。
下面是上述方法的实现。感谢 Richard Zhang 提出这个解决方案。
C++
// A O(n*n) solution to find the minimum of elements to
// be removed
#include
#include
using namespace std;
// Returns the minimum number of removals from either end
// in arr[l..h] so that 2*min becomes greater than max.
int minRemovalsDP(int arr[], int n)
{
// Initialize starting and ending indexes of the maximum
// sized subarray with property 2*min > max
int longest_start = -1, longest_end = 0;
// Choose different elements as starting point
for (int start=0; start max) max = val;
// If the property is violated, then no
// point to continue for a bigger array
if (2 * min <= max) break;
// Update longest_start and longest_end if needed
if (end - start > longest_end - longest_start ||
longest_start == -1)
{
longest_start = start;
longest_end = end;
}
}
}
// If not even a single element follow the property,
// then return n
if (longest_start == -1) return n;
// Return the number of elements to be removed
return (n - (longest_end - longest_start + 1));
}
// Driver program to test above functions
int main()
{
int arr[] = {4, 5, 100, 9, 10, 11, 12, 15, 200};
int n = sizeof(arr)/sizeof(arr[0]);
cout << minRemovalsDP(arr, n);
return 0;
}
Java
// A O(n*n) solution to find the minimum of elements to
// be removed
class GFG {
// Returns the minimum number of removals from either end
// in arr[l..h] so that 2*min becomes greater than max.
static int minRemovalsDP(int arr[], int n) {
// Initialize starting and ending indexes of the maximum
// sized subarray with property 2*min > max
int longest_start = -1, longest_end = 0;
// Choose different elements as starting point
for (int start = 0; start < n; start++) {
// Initialize min and max for the current start
int min = Integer.MAX_VALUE, max = Integer.MIN_VALUE;
// Choose different ending points for current start
for (int end = start; end < n; end++) {
// Update min and max if necessary
int val = arr[end];
if (val < min) {
min = val;
}
if (val > max) {
max = val;
}
// If the property is violated, then no
// point to continue for a bigger array
if (2 * min <= max) {
break;
}
// Update longest_start and longest_end if needed
if (end - start > longest_end - longest_start
|| longest_start == -1) {
longest_start = start;
longest_end = end;
}
}
}
// If not even a single element follow the property,
// then return n
if (longest_start == -1) {
return n;
}
// Return the number of elements to be removed
return (n - (longest_end - longest_start + 1));
}
// Driver program to test above functions
public static void main(String[] args) {
int arr[] = {4, 5, 100, 9, 10, 11, 12, 15, 200};
int n = arr.length;
System.out.println(minRemovalsDP(arr, n));
}
}
// This code is contributed by PrinciRaj1992
蟒蛇3
# A O(n*n) solution to find the minimum of
# elements to be removed
import sys;
# Returns the minimum number of removals
# from either end in arr[l..h] so that
# 2*min becomes greater than max.
def minRemovalsDP(arr, n):
# Initialize starting and ending indexes
# of the maximum sized subarray
# with property 2*min > max
longest_start = -1;
longest_end = 0;
# Choose different elements as starting point
for start in range(n):
# Initialize min and max
# for the current start
min = sys.maxsize;
max = -sys.maxsize;
# Choose different ending points for current start
for end in range(start,n):
# Update min and max if necessary
val = arr[end];
if (val < min):
min = val;
if (val > max):
max = val;
# If the property is violated, then no
# point to continue for a bigger array
if (2 * min <= max):
break;
# Update longest_start and longest_end if needed
if (end - start > longest_end - longest_start or longest_start == -1):
longest_start = start;
longest_end = end;
# If not even a single element follow the property,
# then return n
if (longest_start == -1):
return n;
# Return the number of elements to be removed
return (n - (longest_end - longest_start + 1));
# Driver Code
arr = [4, 5, 100, 9, 10, 11, 12, 15, 200];
n = len(arr);
print(minRemovalsDP(arr, n));
# This code is contributed by mits
C#
// A O(n*n) solution to find the minimum of elements to
// be removed
using System;
public class GFG {
// Returns the minimum number of removals from either end
// in arr[l..h] so that 2*min becomes greater than max.
static int minRemovalsDP(int []arr, int n) {
// Initialize starting and ending indexes of the maximum
// sized subarray with property 2*min > max
int longest_start = -1, longest_end = 0;
// Choose different elements as starting point
for (int start = 0; start < n; start++) {
// Initialize min and max for the current start
int min = int.MaxValue, max = int.MinValue;
// Choose different ending points for current start
for (int end = start; end < n; end++) {
// Update min and max if necessary
int val = arr[end];
if (val < min) {
min = val;
}
if (val > max) {
max = val;
}
// If the property is violated, then no
// point to continue for a bigger array
if (2 * min <= max) {
break;
}
// Update longest_start and longest_end if needed
if (end - start > longest_end - longest_start
|| longest_start == -1) {
longest_start = start;
longest_end = end;
}
}
}
// If not even a single element follow the property,
// then return n
if (longest_start == -1) {
return n;
}
// Return the number of elements to be removed
return (n - (longest_end - longest_start + 1));
}
// Driver program to test above functions
public static void Main() {
int []arr = {4, 5, 100, 9, 10, 11, 12, 15, 200};
int n = arr.Length;
Console.WriteLine(minRemovalsDP(arr, n));
}
}
// This code is contributed by Rajput-Ji
PHP
max
$longest_start = -1;
$longest_end = 0;
// Choose different elements as starting point
for ($start = 0; $start < $n; $start++)
{
// Initialize min and max
// for the current start
$min = PHP_INT_MAX;
$max = PHP_INT_MIN;
// Choose different ending points for current start
for ($end = $start; $end < $n; $end ++)
{
// Update min and max if necessary
$val = $arr[$end];
if ($val < $min) $min = $val;
if ($val > $max) $max = $val;
// If the property is violated, then no
// point to continue for a bigger array
if (2 * $min <= $max) break;
// Update longest_start and longest_end if needed
if ($end - $start > $longest_end - $longest_start ||
$longest_start == -1)
{
$longest_start = $start;
$longest_end = $end;
}
}
}
// If not even a single element follow the property,
// then return n
if ($longest_start == -1) return $n;
// Return the number of elements to be removed
return ($n - ($longest_end - $longest_start + 1));
}
// Driver Code
$arr = array(4, 5, 100, 9, 10, 11, 12, 15, 200);
$n = sizeof($arr);
echo minRemovalsDP($arr, $n);
// This code is contributed by jit_t
?>
Javascript
输出:
4
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。