给定一个由N 个整数组成的数组arr[] ,任务是最小化需要乘以-1的元素数量,以便数组元素的总和为0 。如果不可能使总和为0 ,则打印“-1” 。
例子:
Input: arr[] = {2, 3, 1, 4}
Output: 2
Explanation:
Multiply arr[0] by -1. Therefore, the array modifies to {-2, 3, 1, 4}.
Multiply arr[1] by -1. Therefore, the array modifies to {-2, -3, 1, 4}
Therefore, the sum of the modified array is 0 and the minimum operations required is 2.
Input: arr[] = {2}
Output: -1.
朴素的方法:最简单的方法是以各种可能的方式将数组划分为两个子集。对于每个分区,检查它们的子集和的差异是否为0 。如果发现为0 ,则结果是较小子集的长度。
时间复杂度: O(2 N )
辅助空间: O(N)
高效的方法:为了优化上述方法,思想是使用动态规划。请按照以下步骤解决问题:
- 要使所有数组元素的总和等于0 ,请将给定的数组元素划分为两个总和相等的子集。
- 在给定数组的所有可能的子集中,选择大小最小的子集。
- 如果给定数组的总和为奇数,则没有子集可以使总和为0 ,因此返回-1
- 否则,尝试数组的所有可能的子集总和并检查子集的总和是否等于sum/2 。其中sum是数组所有元素的总和。
- dp[]的递推关系为:
dp(i, j) = min (dp(i+1, j – arr[i]]+1), dp(i+1, j))
where
dp (i, j) represents the minimum operations to make sum j equal to 0 using elements having index [i, N-1].
j represents the current sum.
i represents the current index.
- 使用上面的循环,打印dp(0, sum/2)作为结果。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Initialize dp[][]
int dp[2001][2001];
// Function to find the minimum number
// of operations to make sum of A[] 0
int solve(vector& A, int i,
int sum, int N)
{
// Initialize answer
int res = 2001;
// Base case
if (sum < 0 or (i == N and sum != 0)) {
return 2001;
}
// Otherwise, return 0
if (sum == 0 or i >= N) {
return dp[i][sum] = 0;
}
// Pre-computed subproblem
if (dp[i][sum] != -1) {
return dp[i][sum];
}
// Recurrence relation for finding
// the minimum of the sum of subsets
res = min(solve(A, i + 1, sum - A[i], N) + 1,
solve(A, i + 1, sum, N));
// Return the result
return dp[i][sum] = res;
}
// Function to find the minimum number
// of elements required to be flipped
// to amke sum the array equal to 0
void minOp(vector& A, int N)
{
int sum = 0;
// Find the sum of array
for (auto it : A) {
sum += it;
}
if (sum % 2 == 0) {
// Initialise dp[][] with -1
memset(dp, -1, sizeof(dp));
int ans = solve(A, 0, sum / 2, N);
// No solution exists
if (ans < 0 || ans > N) {
cout << "-1" << endl;
}
// Otherwise
else {
cout << ans << endl;
}
}
// If sum is odd, no
// subset is possible
else {
cout << "-1" << endl;
}
}
// Driver Code
int main()
{
vector A = { 2, 3, 1, 4 };
int N = A.size();
// Function Call
minOp(A, N);
return 0;
}
Java
// Java program for the above approach
class GFG
{
// Initialize dp[][]
static int [][]dp = new int[2001][2001];
// Function to find the minimum number
// of operations to make sum of A[] 0
static int solve(int []A, int i,
int sum, int N)
{
// Initialize answer
int res = 2001;
// Base case
if (sum < 0 || (i == N && sum != 0))
{
return 2001;
}
// Otherwise, return 0
if (sum == 0 || i >= N)
{
return dp[i][sum] = 0;
}
// Pre-computed subproblem
if (dp[i][sum] != -1)
{
return dp[i][sum];
}
// Recurrence relation for finding
// the minimum of the sum of subsets
res = Math.min(solve(A, i + 1, sum - A[i], N) + 1,
solve(A, i + 1, sum, N));
// Return the result
return dp[i][sum] = res;
}
// Function to find the minimum number
// of elements required to be flipped
// to amke sum the array equal to 0
static void minOp(int []A, int N)
{
int sum = 0;
// Find the sum of array
for (int it : A)
{
sum += it;
}
if (sum % 2 == 0)
{
// Initialise dp[][] with -1
for(int i = 0; i < 2001; i++)
{
for (int j = 0; j < 2001; j++)
{
dp[i][j] = -1;
}
}
int ans = solve(A, 0, sum / 2, N);
// No solution exists
if (ans < 0 || ans > N)
{
System.out.print("-1" +"\n");
}
// Otherwise
else
{
System.out.print(ans +"\n");
}
}
// If sum is odd, no
// subset is possible
else
{
System.out.print("-1" +"\n");
}
}
// Driver Code
public static void main(String[] args)
{
int []A = { 2, 3, 1, 4 };
int N = A.length;
// Function Call
minOp(A, N);
}
}
// This code is contributed by 29AjayKumar
Python3
# Python program for the above approach
# Initialize dp[][]
dp = [[-1 for i in range(2001)] for j in range(2001)]
# Function to find the minimum number
# of operations to make sum of A[] 0
def solve(A, i, sum, N):
# Initialize answer
res = 2001
# Base case
if (sum < 0 or (i == N and sum != 0)):
return 2001
# Otherwise, return 0
if (sum == 0 or i >= N):
dp[i][sum] = 0
return 0
# Pre-computed subproblem
if (dp[i][sum] != -1):
return dp[i][sum]
# Recurrence relation for finding
# the minimum of the sum of subsets
res = min(solve(A, i + 1, sum - A[i], N) + 1,
solve(A, i + 1, sum, N))
# Return the result
dp[i][sum] = res
return res
# Function to find the minimum number
# of elements required to be flipped
# to amke sum the array equal to 0
def minOp(A, N):
sum = 0
# Find the sum of array
for it in A:
sum += it
if (sum % 2 == 0):
# Initialise dp[][] with -1
dp = [[-1 for i in range(2001)] for j in range(2001)]
ans = solve(A, 0, sum // 2, N)
# No solution exists
if (ans < 0 or ans > N):
print("-1")
# Otherwise
else:
print(ans)
# If sum is odd, no
# subset is possible
else:
print(-1)
# Driver Code
A = [ 2, 3, 1, 4 ]
N = len(A)
# Function Call
minOp(A, N)
# This code is contributed by rohitsingh07052.
C#
// C# program for the above approach
using System;
using System.Collections.Generic;
public class GFG
{
// Initialize [,]dp
static int [,]dp = new int[2001,2001];
// Function to find the minimum number
// of operations to make sum of []A 0
static int solve(int []A, int i,
int sum, int N)
{
// Initialize answer
int res = 2001;
// Base case
if (sum < 0 || (i == N && sum != 0))
{
return 2001;
}
// Otherwise, return 0
if (sum == 0 || i >= N)
{
return dp[i, sum] = 0;
}
// Pre-computed subproblem
if (dp[i, sum] != -1)
{
return dp[i, sum];
}
// Recurrence relation for finding
// the minimum of the sum of subsets
res = Math.Min(solve(A, i + 1, sum - A[i], N) + 1,
solve(A, i + 1, sum, N));
// Return the result
return dp[i, sum] = res;
}
// Function to find the minimum number
// of elements required to be flipped
// to amke sum the array equal to 0
static void minOp(int []A, int N)
{
int sum = 0;
// Find the sum of array
foreach (int it in A)
{
sum += it;
}
if (sum % 2 == 0)
{
// Initialise [,]dp with -1
for(int i = 0; i < 2001; i++)
{
for (int j = 0; j < 2001; j++)
{
dp[i, j] = -1;
}
}
int ans = solve(A, 0, sum / 2, N);
// No solution exists
if (ans < 0 || ans > N)
{
Console.Write("-1" +"\n");
}
// Otherwise
else
{
Console.Write(ans +"\n");
}
}
// If sum is odd, no
// subset is possible
else
{
Console.Write("-1" +"\n");
}
}
// Driver Code
public static void Main(String[] args)
{
int []A = { 2, 3, 1, 4 };
int N = A.Length;
// Function Call
minOp(A, N);
}
}
// This code is contributed by 29AjayKumar
Javascript
2
时间复杂度: O(S*N),其中 S 是给定数组的总和。
辅助空间: O(S*N)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。