📌  相关文章
📜  所需的最小去除量使得剩余阵列模 M 的总和为 X

📅  最后修改于: 2021-09-17 07:32:32             🧑  作者: Mango

给定一个由N 个正整数和整数XM组成的数组arr[] ,其中0 <= X < M ,任务是找到需要删除的最小元素数,使得剩余数组模M 的总和为等于X 。如果不可能,则打印-1

例子:

朴素方法:最简单的方法是生成给定数组的所有可能子集,对于每个子集,检查删除子集后数组的模M和是否等于X。如果发现是真的,存储它的大小。打印获得的所有此类子集中的最小尺寸。

时间复杂度: O(2 N ) 其中N是给定数组的长度。
辅助空间: O(N)

高效的方法:为了优化上述方法,想法是基于以下观察使用动态规划:

  • 如果S % M > X ,则必须从数组中删除最小数量的总和为S % M – X的元素,以使总和模M等于X
  • 否则,必须删除具有总和S % M + M – X的元素的最小数量,以使总和模M等于X

请按照以下步骤解决问题:

  • 初始化一个dp[]表, table[N + 1][X + 1] ,其中table[i][j]表示要删除的元素的最小数量,这些元素的索引在[0, i]范围内使得它们的总和为j其中X是总和,因此将其删除。
  • 使用一些大值为范围[1, X]中的每个i初始化dp[0][i]
  • dp 转换如下:
  • 打印dp[N][X]作为要删除的最小元素。

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
 
// Function to find the minimum
// elements having sum x
int findSum(vector S, int n, int x)
{
 
    // Initialize dp table
    vector > table(n + 1,
                               vector(
                                   x + 1, 0));
 
    for (int i = 1; i <= x; i++) {
        table[0][i] = INT_MAX - 1;
    }
 
    // Pre-compute subproblems
    for (int i = 1; i <= n; i++) {
 
        for (int j = 1; j <= x; j++) {
 
            // If mod is smaller than element
            if (S[i - 1] > j) {
                table[i][j] = table[i - 1][j];
            }
            else {
 
                // Minimum elements with sum
                // j upto index i
                table[i][j]
                    = min(table[i - 1][j],
                          table[i][j
                                   - S[i - 1]]
                              + 1);
            }
        }
    }
 
    // Return answer
    return (table[n][x] > n)
               ? -1
               : table[n][x];
}
 
// Function to find minimum number
// of removals to make sum % M in
// remaining array is equal to X
void minRemovals(vector arr,
                 int n, int m, int x)
{
 
    // Sum of all elements
    int sum = 0;
    for (int i = 0; i < n; i++) {
        sum += arr[i];
    }
 
    // Sum to be removed
    int requied_Sum = 0;
 
    if (sum % m < x)
        requied_Sum
            = m + sum % m - x;
    else
        requied_Sum
            = sum % m - x;
 
    // Print answer
    cout << findSum(arr, n,
                    requied_Sum);
}
 
// Driver Code
int main()
{
 
    // Given array
    vector arr = { 3, 2, 1, 2 };
 
    // Given size
    int n = arr.size();
 
    // Given mod and x
    int m = 4, x = 2;
 
    // Function call
    minRemovals(arr, n, m, x);
 
    return 0;
}


Java
// Java program for the above approach
import java.util.*;
 
class GFG{
 
// Function to find the minimum
// elements having sum x
static int findSum(int[] S, int n, int x)
{
     
    // Initialize dp table
    int [][]table = new int[n + 1][x + 1];
     
    for(int i = 1; i <= x; i++)
    {
        table[0][i] = Integer.MAX_VALUE - 1;
    }
 
    // Pre-compute subproblems
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= x; j++)
        {
             
            // If mod is smaller than element
            if (S[i - 1] > j)
            {
                table[i][j] = table[i - 1][j];
            }
            else
            {
                 
                // Minimum elements with sum
                // j upto index i
                table[i][j] = Math.min(table[i - 1][j],
                                       table[i][j - S[i - 1]] + 1);
            }
        }
    }
 
    // Return answer
    return (table[n][x] > n) ? -1 : table[n][x];
}
 
// Function to find minimum number
// of removals to make sum % M in
// remaining array is equal to X
static void minRemovals(int[] arr, int n,
                        int m, int x)
{
     
    // Sum of all elements
    int sum = 0;
    for(int i = 0; i < n; i++)
    {
        sum += arr[i];
    }
 
    // Sum to be removed
    int requied_Sum = 0;
 
    if (sum % m < x)
        requied_Sum = m + sum % m - x;
    else
        requied_Sum = sum % m - x;
 
    // Print answer
    System.out.print(findSum(arr, n,
                             requied_Sum));
}
 
// Driver Code
public static void main(String[] args)
{
     
    // Given array
    int[] arr = { 3, 2, 1, 2 };
 
    // Given size
    int n = arr.length;
 
    // Given mod and x
    int m = 4, x = 2;
 
    // Function call
    minRemovals(arr, n, m, x);
}
}
 
// This code is contributed by Amit Katiyar


Python3
# Python3 program for the above approach
import sys
 
# Function to find the minimum
# elements having sum x
def findSum(S, n, x):
     
    # Initialize dp table
    table = [[0 for x in range(x + 1)]
                for y in range(n + 1)]
 
    for i in range(1, x + 1):
        table[0][i] = sys.maxsize - 1
 
    # Pre-compute subproblems
    for i in range(1, n + 1):
        for j in range(1, x + 1):
 
            # If mod is smaller than element
            if (S[i - 1] > j):
                table[i][j] = table[i - 1][j]
 
            else:
 
                # Minimum elements with sum
                # j upto index i
                table[i][j] = min(table[i - 1][j],
                                  table[i][j - S[i - 1]] + 1)
                                   
    # Return answer
    if (table[n][x] > n):
        return -1
         
    return table[n][x]
 
# Function to find minimum number
# of removals to make sum % M in
# remaining array is equal to X
def minRemovals(arr, n, m, x):
     
    # Sum of all elements
    sum = 0
    for i in range(n):
        sum += arr[i]
 
    # Sum to be removed
    requied_Sum = 0
 
    if (sum % m < x):
        requied_Sum = m + sum % m - x
    else:
        requied_Sum = sum % m - x
 
    # Print answer
    print(findSum(arr, n,
                  requied_Sum))
 
# Driver Code
if __name__ == "__main__":
 
    # Given array
    arr = [ 3, 2, 1, 2 ]
 
    # Given size
    n = len(arr)
 
    # Given mod and x
    m = 4
    x = 2
 
    # Function call
    minRemovals(arr, n, m, x)
 
# This code is contributed by chitranayal


C#
// C# program for the
// above approach
using System;
class GFG{
 
// Function to find the minimum
// elements having sum x
static int findSum(int[] S,
                   int n, int x)
{   
  // Initialize dp table
  int [,]table = new int[n + 1,
                         x + 1];
 
  for(int i = 1; i <= x; i++)
  {
    table[0, i] = int.MaxValue - 1;
  }
 
  // Pre-compute subproblems
  for(int i = 1; i <= n; i++)
  {
    for(int j = 1; j <= x; j++)
    {
 
      // If mod is smaller than
      // element
      if (S[i - 1] > j)
      {
        table[i, j] = table[i - 1, j];
      }
      else
      {
 
        // Minimum elements with sum
        // j upto index i
        table[i, j] = Math.Min(table[i - 1, j],
                              table[i, j -
                              S[i - 1]] + 1);
      }
    }
  }
 
  // Return answer
  return (table[n, x] > n) ? -1 :
          table[n, x];
}
 
// Function to find minimum number
// of removals to make sum % M in
// remaining array is equal to X
static void minRemovals(int[] arr, int n,
                        int m, int x)
{   
  // Sum of all elements
  int sum = 0;
  for(int i = 0; i < n; i++)
  {
    sum += arr[i];
  }
 
  // Sum to be removed
  int requied_Sum = 0;
 
  if (sum % m < x)
    requied_Sum = m + sum %
                  m - x;
  else
    requied_Sum = sum % m - x;
 
  // Print answer
  Console.Write(findSum(arr, n,
                        requied_Sum));
}
 
// Driver Code
public static void Main(String[] args)
{   
  // Given array
  int[] arr = {3, 2, 1, 2};
 
  // Given size
  int n = arr.Length;
 
  // Given mod and x
  int m = 4, x = 2;
 
  // Function call
  minRemovals(arr, n, m, x);
}
}
 
// This code is contributed by Amit Katiyar


Javascript


输出
1

时间复杂度: O(N*X),其中 N 是给定数组的长度,X 是给定的整数。
辅助空间: O(N*X)

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程