📌  相关文章
📜  Array 中的最小删除量以使相邻元素的差异不减少

📅  最后修改于: 2021-09-22 10:11:30             🧑  作者: Mango

给定一个由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应该成立。)

例子:

朴素的方法:朴素的方法是生成给定数组的所有子集并检查是否有任何子集满足条件。如果是,请检查删除了多少元素以获得该子集,然后取最小值。

下面是上述方法的实现:

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)

使用动态规划的有效方法:可以通过找到满足条件的子集的最大大小来解决问题,而不是找到最小的删除次数。请按照以下步骤解决问题:

  1. 创建一个二维数组dp ,其中dp[i][j]存储要从索引1 到 i删除的满足条件的最小元素数:
    1. A[i]-A[i-1]=A[j]
  2. 使用i0迭代到 N-1 ,然后执行以下操作:
    1. 1存储在dp[i][0] 中,因为大小将为1
    2. 使用ji-1迭代到 0并执行以下操作:
      1. 检查A[i]是否大于A[j]。如果它更大,请执行以下操作:
        1. 将 A[i]-A[j] 存储在一个变量中,比如diff。
        2. 使用k0迭代到 diff ,并执行以下操作:
          1. dp[i]dp[j][k]+1之间的最大值存储在dp[i] 中
          2. 因此,过渡是:
            1. dp[i]=max(dp[i], dp[j][k]+1)
  3. 使用i0迭代到 MAX ,并将dp[N-1][i]的最大值存储在一个变量中,比如maxSetSize。
  4. 答案是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)

使用优化动态规划的高效方法:在上述方法中,重复计算每个k0diff的最小值。为了避免这种情况,可以维护一个二维前缀最大数组pref ,其中pref[i][j]存储子集大小的最大值,这样从1 到 i ,以下条件成立:

  1. 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 现场工作专业课程学生竞争性编程现场课程