给定一个由N 个非负整数组成的数组A ,任务是计算要删除的最小元素数,以便满足以下条件:
- 元素按非递减顺序排列。 (形式上,对于每个 i (1 ≤ i ≤ N-1),条件A i+1 >= A i应该成立。)
- 相邻元素之间的差异应按非递减顺序排列。 (形式上,对于每个 i (2 ≤ i ≤ N-1),条件A i -A i-1 ≤ A i+1 -A i应该成立。)
例子:
Input: A = {1, 4, 5, 7, 20, 21}
Output:
2
Explanation: By deleting 5 and 21, the array {1, 4, 7, 20} is obtained. Here the elements are in non-decreasing order and the difference between adjacent elements are 3, 3, 13 which are in non-decreasing order.
Input: A = {3, 2}
Output:
1
Explanation: The original array doesn’t satisfy the first condition. Hence, either of the elements can be deleted to get an array with a single element.
朴素的方法:朴素的方法是生成给定数组的所有子集并检查是否有任何子集满足条件。如果是,请检查删除了多少元素以获得该子集,然后取最小值。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function for finding minimum deletions so that the array
// becomes non decreasing and the difference between adjacent
// elements also becomes non decreasing
int minimumDeletions(int A[], int N)
{
// initialize answer to a large value
int ans = INT_MAX;
// generating all subsets
for (int i = 1; i < (1 << N); i++) {
vector temp;
for (int j = 0; j < N; j++) {
if ((i & (1 << j)) != 0) {
temp.push_back(A[j]);
}
}
int flag = 0;
// checking the first condition
for (int j = 1; j < temp.size(); j++)
if (temp[j] < temp[j - 1])
flag = 1;
// checking the second condition
for (int j = 1; j < temp.size() - 1; j++)
if (temp[j] - temp[j - 1]
> temp[j + 1] - temp[j])
flag = 1;
// if both conditions are satisfied consider the
// answer for minimum
if (flag == 0) {
ans = min(ans, N - (int)temp.size());
}
}
return ans;
}
// Driver code
int main()
{
// Input
int A[] = { 1, 4, 5, 7, 20, 21 };
int N = sizeof(A) / sizeof(A[0]);
// Function call
cout << minimumDeletions(A, N) << endl;
return 0;
}
Java
// Java program for the above approach
import java.util.ArrayList;
class GFG{
// Function for finding minimum deletions so that the array
// becomes non decreasing and the difference between adjacent
// elements also becomes non decreasing
public static int minimumDeletions(int A[], int N)
{
// initialize answer to a large value
int ans = Integer.MAX_VALUE;
// generating all subsets
for (int i = 1; i < (1 << N); i++) {
ArrayList temp = new ArrayList();
for (int j = 0; j < N; j++) {
if ((i & (1 << j)) != 0) {
temp.add(A[j]);
}
}
int flag = 0;
// checking the first condition
for (int j = 1; j < temp.size(); j++)
if (temp.get(j) < temp.get(j - 1))
flag = 1;
// checking the second condition
for (int j = 1; j < temp.size() - 1; j++)
if (temp.get(j) - temp.get(j - 1)
> temp.get(j + 1) - temp.get(j))
flag = 1;
// if both conditions are satisfied consider the
// answer for minimum
if (flag == 0) {
ans = Math.min(ans, N - (int)temp.size());
}
}
return ans;
}
// Driver code
public static void main(String args[])
{
// Input
int A[] = { 1, 4, 5, 7, 20, 21 };
int N = A.length;
// Function call
System.out.println(minimumDeletions(A, N));
}
}
// This code is contributed by saurabh_jaiswal.
Python3
# Python program for the above approach
# Function for finding minimum deletions so that the array
# becomes non decreasing and the difference between adjacent
# elements also becomes non decreasing
def minimumDeletions(A, N):
# initialize answer to a large value
ans = 10**8
# generating all subsets
for i in range(1,(1< temp[j + 1] - temp[j]):
flag = 1
# if both conditions are satisfied consider the
# answer for minimum
if (flag == 0):
ans = min(ans, N - len(temp))
return ans
# Driver code
if __name__ == '__main__':
# Input
A= [1, 4, 5, 7, 20, 21]
N = len(A)
# Function call
print (minimumDeletions(A, N))
# This code is contributed by mohit kumar 29.
C#
// C# program for the above approach
using System;
using System.Collections.Generic;
class GFG{
// Function for finding minimum deletions so that the array
// becomes non decreasing and the difference between adjacent
// elements also becomes non decreasing
static int minimumDeletions(int []A, int N)
{
// initialize answer to a large value
int ans = Int32.MaxValue;
// generating all subsets
for (int i = 1; i < (1 << N); i++) {
List temp = new List();
for (int j = 0; j < N; j++) {
if ((i & (1 << j)) != 0) {
temp.Add(A[j]);
}
}
int flag = 0;
// checking the first condition
for (int j = 1; j < temp.Count; j++)
if (temp[j] < temp[j - 1])
flag = 1;
// checking the second condition
for (int j = 1; j < temp.Count - 1; j++)
if (temp[j] - temp[j - 1]
> temp[j + 1] - temp[j])
flag = 1;
// if both conditions are satisfied consider the
// answer for minimum
if (flag == 0) {
ans = Math.Min(ans, N - temp.Count);
}
}
return ans;
}
// Driver code
public static void Main()
{
// Input
int []A = { 1, 4, 5, 7, 20, 21 };
int N = A.Length;
// Function call
Console.Write(minimumDeletions(A, N));
}
}
// This code is contributed by ipg2016107.
Javascript
C++
#include
using namespace std;
// the maximum value of A[i]
#define MAX 100001
// Function for finding minimum deletions
// so that the array becomes non-decreasing
// and the difference between adjacent
// elements is also non-decreasing
int minimumDeletions(int A[], int N)
{
// initializing the dp table
// and setting all values to 0
int dp[N][MAX];
for (int i = 0; i < N; i++)
for (int j = 0; j < MAX; j++)
dp[i][j] = 0;
// Find the maximum size valid set
// that can be taken and then subtract
// its size from N to get
// minimum number of deletions
for (int i = 0; i < N; i++) {
// when selecting only current element
// and deleting all elements
// from 0 to i-1 inclusive
dp[i][0] = 1;
for (int j = i - 1; j >= 0; j--) {
// if this is true moving from
// index j to i is possible
if (A[i] >= A[j]) {
int diff = A[i] - A[j];
// iterate over all elements from 0
// to diff and find the max
for (int k = 0; k <= diff; k++) {
dp[i]
= max(dp[i], dp[j][k] + 1);
}
}
}
}
// take the max set size
// from dp[N-1][0] to dp[N-1][MAX]
int maxSetSize = -1;
for (int i = 0; i < MAX; i++)
maxSetSize = max(maxSetSize, dp[N - 1][i]);
return N - maxSetSize;
}
// Driver code
int main()
{
// Input
int A[] = { 1, 4, 5, 7, 20, 21 };
int N = sizeof(A) / sizeof(A[0]);
// Function call
cout << minimumDeletions(A, N) << endl;
return 0;
}
Java
// Java program for the above approach
import java.io.*;
class GFG {
// the maximum value of A[i]
static int MAX = 100001;
// Function for finding minimum deletions
// so that the array becomes non-decreasing
// and the difference between adjacent
// elements is also non-decreasing
static int minimumDeletions(int A[], int N)
{
// initializing the dp table
// and setting all values to 0
int[][] dp = new int[N][MAX];
for (int i = 0; i < N; i++)
for (int j = 0; j < MAX; j++)
dp[i][j] = 0;
// Find the maximum size valid set
// that can be taken and then subtract
// its size from N to get
// minimum number of deletions
for (int i = 0; i < N; i++) {
// when selecting only current element
// and deleting all elements
// from 0 to i-1 inclusive
dp[i][0] = 1;
for (int j = i - 1; j >= 0; j--) {
// if this is true moving from
// index j to i is possible
if (A[i] >= A[j]) {
int diff = A[i] - A[j];
// iterate over all elements from 0
// to diff and find the max
for (int k = 0; k <= diff; k++) {
dp[i]
= Math.max(dp[i], dp[j][k] + 1);
}
}
}
}
// take the max set size
// from dp[N-1][0] to dp[N-1][MAX]
int maxSetSize = -1;
for (int i = 0; i < MAX; i++)
maxSetSize = Math.max(maxSetSize, dp[N - 1][i]);
return N - maxSetSize;
}
// Driver Code
public static void main(String[] args)
{
int A[] = { 1, 4, 5, 7, 20, 21 };
int N = A.length;
// Function call
System.out.println(minimumDeletions(A, N));
}
}
// This code is contributed by code_hunt.
C#
// C# program for the above approach
using System;
class GFG{
// The maximum value of A[i]
static int MAX = 100001;
// Function for finding minimum deletions
// so that the array becomes non-decreasing
// and the difference between adjacent
// elements is also non-decreasing
static int minimumDeletions(int[] A, int N)
{
// Initializing the dp table
// and setting all values to 0
int[,] dp = new int[N, MAX];
for(int i = 0; i < N; i++)
for(int j = 0; j < MAX; j++)
dp[i, j] = 0;
// Find the maximum size valid set
// that can be taken and then subtract
// its size from N to get
// minimum number of deletions
for(int i = 0; i < N; i++)
{
// When selecting only current element
// and deleting all elements
// from 0 to i-1 inclusive
dp[i, 0] = 1;
for(int j = i - 1; j >= 0; j--)
{
// If this is true moving from
// index j to i is possible
if (A[i] >= A[j])
{
int diff = A[i] - A[j];
// Iterate over all elements from 0
// to diff and find the max
for(int k = 0; k <= diff; k++)
{
dp[i, diff] = Math.Max(dp[i, diff],
dp[j, k] + 1);
}
}
}
}
// Take the max set size
// from dp[N-1][0] to dp[N-1][MAX]
int maxSetSize = -1;
for(int i = 0; i < MAX; i++)
maxSetSize = Math.Max(maxSetSize, dp[N - 1, i]);
return N - maxSetSize;
}
// Driver Code
public static void Main()
{
int[] A = { 1, 4, 5, 7, 20, 21 };
int N = A.Length;
// Function call
Console.Write(minimumDeletions(A, N));
}
}
// This code is contributed by sanjoy_62
Javascript
C++
// C++ program for the above approach
#include
using namespace std;
// the maximum value of A[i]
#define MAX 100001
// Function for finding minimum deletions
// so that the array becomes non-decreasing
// and the difference between adjacent
// elements is also non-decreasing
int minimumDeletions(int A[], int N)
{
// initialize the dp table
// and set all values to 0
// pref[i][j] will contain min(dp[i][0],
// dp[i][1], ...dp[i][j])
int dp[N][MAX];
int pref[N][MAX];
for (int i = 0; i < N; i++) {
for (int j = 0; j < MAX; j++) {
dp[i][j] = 0;
pref[i][j] = 0;
}
}
// find the maximum sized valid set
// possible and then subtract its
// size from N to get
// minimum number of deletions
for (int i = 0; i < N; i++) {
// when selecting only the current element and
// deleting all elements from 0 to i-1 inclusive
dp[i][0] = 1;
for (int j = i - 1; j >= 0; j--) {
// if this is true,
// moving from index j to i is possible
if (A[i] >= A[j]) {
int diff = A[i] - A[j];
// we can get min(dp[j][0], .. dp[j])
// from pref array;
dp[i]
= max(dp[i], pref[j] + 1);
}
}
// construct the prefix array for this element
pref[i][0] = dp[i][0];
for (int j = 1; j < MAX; j++)
pref[i][j] = max(dp[i][j], pref[i][j - 1]);
}
// take the max set size from dp[N-1][0] to dp[N-1][MAX]
int maxSetSize = -1;
for (int i = 0; i < MAX; i++)
maxSetSize = max(maxSetSize, dp[N - 1][i]);
return N - maxSetSize;
}
// Driver code
int main()
{
int A[] = { 1, 4, 5, 7, 20, 21 };
int N = sizeof(A) / sizeof(A[0]);
// Function call
cout << minimumDeletions(A, N) << endl;
return 0;
}
2
时间复杂度: O(N*2 N )
辅助空间: O(N)
使用动态规划的有效方法:可以通过找到满足条件的子集的最大大小来解决问题,而不是找到最小的删除次数。请按照以下步骤解决问题:
- 创建一个二维数组dp ,其中dp[i][j]存储要从索引1 到 i删除的满足条件的最小元素数:
- A[i]-A[i-1]=A[j]
- 使用i从0迭代到 N-1 ,然后执行以下操作:
- 将1存储在dp[i][0] 中,因为大小将为1 。
- 使用j从i-1迭代到 0并执行以下操作:
- 检查A[i]是否大于A[j]。如果它更大,请执行以下操作:
- 将 A[i]-A[j] 存储在一个变量中,比如diff。
- 使用k从0迭代到 diff ,并执行以下操作:
- 将dp[i]和dp[j][k]+1之间的最大值存储在dp[i] 中。
- 因此,过渡是:
- dp[i]=max(dp[i], dp[j][k]+1)
- 检查A[i]是否大于A[j]。如果它更大,请执行以下操作:
- 使用i从0迭代到 MAX ,并将dp[N-1][i]的最大值存储在一个变量中,比如maxSetSize。
- 答案是N-maxSetSize 。
下面是实现该方法的代码
C++
#include
using namespace std;
// the maximum value of A[i]
#define MAX 100001
// Function for finding minimum deletions
// so that the array becomes non-decreasing
// and the difference between adjacent
// elements is also non-decreasing
int minimumDeletions(int A[], int N)
{
// initializing the dp table
// and setting all values to 0
int dp[N][MAX];
for (int i = 0; i < N; i++)
for (int j = 0; j < MAX; j++)
dp[i][j] = 0;
// Find the maximum size valid set
// that can be taken and then subtract
// its size from N to get
// minimum number of deletions
for (int i = 0; i < N; i++) {
// when selecting only current element
// and deleting all elements
// from 0 to i-1 inclusive
dp[i][0] = 1;
for (int j = i - 1; j >= 0; j--) {
// if this is true moving from
// index j to i is possible
if (A[i] >= A[j]) {
int diff = A[i] - A[j];
// iterate over all elements from 0
// to diff and find the max
for (int k = 0; k <= diff; k++) {
dp[i]
= max(dp[i], dp[j][k] + 1);
}
}
}
}
// take the max set size
// from dp[N-1][0] to dp[N-1][MAX]
int maxSetSize = -1;
for (int i = 0; i < MAX; i++)
maxSetSize = max(maxSetSize, dp[N - 1][i]);
return N - maxSetSize;
}
// Driver code
int main()
{
// Input
int A[] = { 1, 4, 5, 7, 20, 21 };
int N = sizeof(A) / sizeof(A[0]);
// Function call
cout << minimumDeletions(A, N) << endl;
return 0;
}
Java
// Java program for the above approach
import java.io.*;
class GFG {
// the maximum value of A[i]
static int MAX = 100001;
// Function for finding minimum deletions
// so that the array becomes non-decreasing
// and the difference between adjacent
// elements is also non-decreasing
static int minimumDeletions(int A[], int N)
{
// initializing the dp table
// and setting all values to 0
int[][] dp = new int[N][MAX];
for (int i = 0; i < N; i++)
for (int j = 0; j < MAX; j++)
dp[i][j] = 0;
// Find the maximum size valid set
// that can be taken and then subtract
// its size from N to get
// minimum number of deletions
for (int i = 0; i < N; i++) {
// when selecting only current element
// and deleting all elements
// from 0 to i-1 inclusive
dp[i][0] = 1;
for (int j = i - 1; j >= 0; j--) {
// if this is true moving from
// index j to i is possible
if (A[i] >= A[j]) {
int diff = A[i] - A[j];
// iterate over all elements from 0
// to diff and find the max
for (int k = 0; k <= diff; k++) {
dp[i]
= Math.max(dp[i], dp[j][k] + 1);
}
}
}
}
// take the max set size
// from dp[N-1][0] to dp[N-1][MAX]
int maxSetSize = -1;
for (int i = 0; i < MAX; i++)
maxSetSize = Math.max(maxSetSize, dp[N - 1][i]);
return N - maxSetSize;
}
// Driver Code
public static void main(String[] args)
{
int A[] = { 1, 4, 5, 7, 20, 21 };
int N = A.length;
// Function call
System.out.println(minimumDeletions(A, N));
}
}
// This code is contributed by code_hunt.
C#
// C# program for the above approach
using System;
class GFG{
// The maximum value of A[i]
static int MAX = 100001;
// Function for finding minimum deletions
// so that the array becomes non-decreasing
// and the difference between adjacent
// elements is also non-decreasing
static int minimumDeletions(int[] A, int N)
{
// Initializing the dp table
// and setting all values to 0
int[,] dp = new int[N, MAX];
for(int i = 0; i < N; i++)
for(int j = 0; j < MAX; j++)
dp[i, j] = 0;
// Find the maximum size valid set
// that can be taken and then subtract
// its size from N to get
// minimum number of deletions
for(int i = 0; i < N; i++)
{
// When selecting only current element
// and deleting all elements
// from 0 to i-1 inclusive
dp[i, 0] = 1;
for(int j = i - 1; j >= 0; j--)
{
// If this is true moving from
// index j to i is possible
if (A[i] >= A[j])
{
int diff = A[i] - A[j];
// Iterate over all elements from 0
// to diff and find the max
for(int k = 0; k <= diff; k++)
{
dp[i, diff] = Math.Max(dp[i, diff],
dp[j, k] + 1);
}
}
}
}
// Take the max set size
// from dp[N-1][0] to dp[N-1][MAX]
int maxSetSize = -1;
for(int i = 0; i < MAX; i++)
maxSetSize = Math.Max(maxSetSize, dp[N - 1, i]);
return N - maxSetSize;
}
// Driver Code
public static void Main()
{
int[] A = { 1, 4, 5, 7, 20, 21 };
int N = A.Length;
// Function call
Console.Write(minimumDeletions(A, N));
}
}
// This code is contributed by sanjoy_62
Javascript
2
时间复杂度: O(N 2 *M),其中 M 是 A 中的最大元素,
辅助空间: O(N*M)
使用优化动态规划的高效方法:在上述方法中,重复计算每个k从0到diff的最小值。为了避免这种情况,可以维护一个二维前缀最大数组pref ,其中pref[i][j]存储子集大小的最大值,这样从1 到 i ,以下条件成立:
- A[i]-A[i-1]=A[j]
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// the maximum value of A[i]
#define MAX 100001
// Function for finding minimum deletions
// so that the array becomes non-decreasing
// and the difference between adjacent
// elements is also non-decreasing
int minimumDeletions(int A[], int N)
{
// initialize the dp table
// and set all values to 0
// pref[i][j] will contain min(dp[i][0],
// dp[i][1], ...dp[i][j])
int dp[N][MAX];
int pref[N][MAX];
for (int i = 0; i < N; i++) {
for (int j = 0; j < MAX; j++) {
dp[i][j] = 0;
pref[i][j] = 0;
}
}
// find the maximum sized valid set
// possible and then subtract its
// size from N to get
// minimum number of deletions
for (int i = 0; i < N; i++) {
// when selecting only the current element and
// deleting all elements from 0 to i-1 inclusive
dp[i][0] = 1;
for (int j = i - 1; j >= 0; j--) {
// if this is true,
// moving from index j to i is possible
if (A[i] >= A[j]) {
int diff = A[i] - A[j];
// we can get min(dp[j][0], .. dp[j])
// from pref array;
dp[i]
= max(dp[i], pref[j] + 1);
}
}
// construct the prefix array for this element
pref[i][0] = dp[i][0];
for (int j = 1; j < MAX; j++)
pref[i][j] = max(dp[i][j], pref[i][j - 1]);
}
// take the max set size from dp[N-1][0] to dp[N-1][MAX]
int maxSetSize = -1;
for (int i = 0; i < MAX; i++)
maxSetSize = max(maxSetSize, dp[N - 1][i]);
return N - maxSetSize;
}
// Driver code
int main()
{
int A[] = { 1, 4, 5, 7, 20, 21 };
int N = sizeof(A) / sizeof(A[0]);
// Function call
cout << minimumDeletions(A, N) << endl;
return 0;
}
2
时间复杂度: O(N*M+N 2 ),其中 M 是 A 中的最大元素,
辅助空间: O(N*M)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。