给定一个由N 个正整数和整数X和M组成的数组arr[] ,其中0 <= X < M ,任务是找到需要删除的最小元素数,使得剩余数组模M 的总和为等于X 。如果不可能,则打印-1 。
例子:
Input: arr[] = {3, 2, 1, 2}, M = 4, X = 2
Output: 1
Explanation: One of the elements at indices (0-based) 1 or 3 can be removed. If arr[1] is removed, then arr[] modifies to {3, 1, 2} and sum % M = 6 % 4 = 2 which is equal to X = 2.
Input: arr[] = {3, 2, 1, 3}, M = 4, X = 3
Output: 1
Explanation: Remove element arr[1]( = 2). Therefore, arr[] modifies to {3, 1, 3} and sum % M = 7 % 4 = 3 which is equal to X = 3.
朴素方法:最简单的方法是生成给定数组的所有可能子集,对于每个子集,检查删除子集后数组的模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[i][j] = min(dp[i-1][j], dp[i][j-arr[i-1]]+1)
where, i is in the range [1, N] and j is in the range [1, X].
- 打印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 现场工作专业课程和学生竞争性编程现场课程。