Minimize count of flips required to make sum of the given array equal to 0
Last Updated :
09 Nov, 2023
Given an array arr[] consisting of N integers, the task is to minimize the count of elements required to be multiplied by -1 such that the sum of array elements is 0. If it is not possible to make the sum 0, print “-1”.
Examples:
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
Naive Approach: The simplest approach is to divide the array into two subsets in every possible way. For each division, check if the difference of their subset-sum is 0 or not. If found to be 0, then the length of the smaller subset is the result.
Time Complexity: O(2N)
Auxiliary Space: O(N)
Efficient Approach: To optimize the above approach, the idea is to use Dynamic Programming. Follow the steps to solve the problem:
- To make the sum of all array elements equal to 0, divide the given array elements into two subsets having an equal sum.
- Out of all the subsets possible of the given array, the subset whose size is the minimum of all is chosen.
- If the sum of the given array is odd, no subset is possible to make the sum 0, hence return -1
- Else, try all possible subset sums of the array and check if the sum of the subset is equal to sum/2. where the sum is the sum of all elements of the array.
- The recurrence relation of dp[] is:
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.
- Using the above recurrence, print dp(0, sum/2) as the result.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int dp[2001][2001];
int solve(vector< int >& A, int i,
int sum, int N)
{
int res = 2001;
if (sum < 0 or (i == N and sum != 0)) {
return 2001;
}
if (sum == 0 or i >= N) {
return dp[i][sum] = 0;
}
if (dp[i][sum] != -1) {
return dp[i][sum];
}
res = min(solve(A, i + 1, sum - A[i], N) + 1,
solve(A, i + 1, sum, N));
return dp[i][sum] = res;
}
void minOp(vector< int >& A, int N)
{
int sum = 0;
for ( auto it : A) {
sum += it;
}
if (sum % 2 == 0) {
memset (dp, -1, sizeof (dp));
int ans = solve(A, 0, sum / 2, N);
if (ans < 0 || ans > N) {
cout << "-1" << endl;
}
else {
cout << ans << endl;
}
}
else {
cout << "-1" << endl;
}
}
int main()
{
vector< int > A = { 2, 3, 1, 4 };
int N = A.size();
minOp(A, N);
return 0;
}
|
Java
class GFG
{
static int [][]dp = new int [ 2001 ][ 2001 ];
static int solve( int []A, int i,
int sum, int N)
{
int res = 2001 ;
if (sum < 0 || (i == N && sum != 0 ))
{
return 2001 ;
}
if (sum == 0 || i >= N)
{
return dp[i][sum] = 0 ;
}
if (dp[i][sum] != - 1 )
{
return dp[i][sum];
}
res = Math.min(solve(A, i + 1 , sum - A[i], N) + 1 ,
solve(A, i + 1 , sum, N));
return dp[i][sum] = res;
}
static void minOp( int []A, int N)
{
int sum = 0 ;
for ( int it : A)
{
sum += it;
}
if (sum % 2 == 0 )
{
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);
if (ans < 0 || ans > N)
{
System.out.print( "-1" + "\n" );
}
else
{
System.out.print(ans + "\n" );
}
}
else
{
System.out.print( "-1" + "\n" );
}
}
public static void main(String[] args)
{
int []A = { 2 , 3 , 1 , 4 };
int N = A.length;
minOp(A, N);
}
}
|
Python3
dp = [[ - 1 for i in range ( 2001 )] for j in range ( 2001 )]
def solve(A, i, sum , N):
res = 2001
if ( sum < 0 or (i = = N and sum ! = 0 )):
return 2001
if ( sum = = 0 or i > = N):
dp[i][ sum ] = 0
return 0
if (dp[i][ sum ] ! = - 1 ):
return dp[i][ sum ]
res = min (solve(A, i + 1 , sum - A[i], N) + 1 ,
solve(A, i + 1 , sum , N))
dp[i][ sum ] = res
return res
def minOp(A, N):
sum = 0
for it in A:
sum + = it
if ( sum % 2 = = 0 ):
dp = [[ - 1 for i in range ( 2001 )] for j in range ( 2001 )]
ans = solve(A, 0 , sum / / 2 , N)
if (ans < 0 or ans > N):
print ( "-1" )
else :
print (ans)
else :
print ( - 1 )
A = [ 2 , 3 , 1 , 4 ]
N = len (A)
minOp(A, N)
|
C#
using System;
using System.Collections.Generic;
public class GFG
{
static int [,]dp = new int [2001,2001];
static int solve( int []A, int i,
int sum, int N)
{
int res = 2001;
if (sum < 0 || (i == N && sum != 0))
{
return 2001;
}
if (sum == 0 || i >= N)
{
return dp[i, sum] = 0;
}
if (dp[i, sum] != -1)
{
return dp[i, sum];
}
res = Math.Min(solve(A, i + 1, sum - A[i], N) + 1,
solve(A, i + 1, sum, N));
return dp[i, sum] = res;
}
static void minOp( int []A, int N)
{
int sum = 0;
foreach ( int it in A)
{
sum += it;
}
if (sum % 2 == 0)
{
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);
if (ans < 0 || ans > N)
{
Console.Write( "-1" + "\n" );
}
else
{
Console.Write(ans + "\n" );
}
}
else
{
Console.Write( "-1" + "\n" );
}
}
public static void Main(String[] args)
{
int []A = { 2, 3, 1, 4 };
int N = A.Length;
minOp(A, N);
}
}
|
Javascript
<script>
let dp= [];
for ( var i=0; i<2001; i++) {
dp[i] = [];
for ( var j=0; j<2001; j++) {
dp[i][j] = -1;
}
}
function solve( A, i, sum, N){
let res = 2001;
if (sum < 0 || (i == N && sum != 0)) {
return 2001;
}
if (sum == 0 || i >= N) {
dp[i][sum] = 0;
return dp[i][sum];
}
if (dp[i][sum] != -1) {
return dp[i][sum];
}
res = Math.min(solve(A, i + 1, sum - A[i], N) + 1,
solve(A, i + 1, sum, N));
dp[i][sum] = res;
return dp[i][sum];
}
function minOp(A, N){
let sum = 0;
for (let i =0; i< A.length; i++) {
sum += A[i];
}
if (sum % 2 == 0) {
let dp= [];
for ( var i=0; i<2001; i++) {
dp[i] = [];
for ( var j=0; j<2001; j++) {
dp[i][j] = -1;
}
}
let ans = solve(A, 0, Math.floor(sum / 2), N);
if (ans < 0 || ans > N) {
document.write( "-1 <br>" );
}
else {
document.write(ans, "<br>" );
}
}
else {
document.write( "-1 <br>" );
}
}
let A = [ 2, 3, 1, 4 ];
let N = A.length;
minOp(A, N);
</script>
|
Time Complexity: O(S*N), where S is the sum of the given array.
Auxiliary Space: O(S*N)
Efficient approach : Using DP Tabulation method ( Iterative approach )
The approach to solve this problem is same but DP tabulation(bottom-up) method is better then Dp + memoization(top-down) because memoization method needs extra stack space of recursion calls.
Implementation :
C++
#include <bits/stdc++.h>
using namespace std;
int dp[2001][2001];
void minOp(vector< int >& A, int N)
{
int sum = 0;
for ( auto it : A) {
sum += it;
}
if (sum % 2 == 0) {
int target = sum / 2;
for ( int i = 0; i <= N; i++) {
dp[i][0] = 0;
}
for ( int j = 1; j <= target; j++) {
dp[N][j] = 2001;
}
for ( int i = N - 1; i >= 0; i--) {
for ( int j = 1; j <= target; j++) {
if (j >= A[i]) {
dp[i][j] = min(dp[i + 1][j],
dp[i + 1][j - A[i]] + 1);
}
else {
dp[i][j] = dp[i + 1][j];
}
}
}
if (dp[0][target] >= 2001) {
cout << "-1" << endl;
}
else {
cout << dp[0][target] << endl;
}
}
else {
cout << "-1" << endl;
}
}
int main()
{
vector< int > A = { 2, 3, 1, 4 };
int N = A.size();
minOp(A, N);
return 0;
}
|
Java
import java.util.Arrays;
import java.util.List;
public class Main {
static int [][] dp;
static void minOp(List<Integer> A, int N)
{
int sum = 0 ;
for ( int it : A) {
sum += it;
}
if (sum % 2 == 0 ) {
int target = sum / 2 ;
dp = new int [N + 1 ][target + 1 ];
for ( int i = 0 ; i <= N; i++) {
Arrays.fill(dp[i], 0 );
}
for ( int j = 1 ; j <= target; j++) {
dp[N][j] = 2001 ;
}
for ( int i = N - 1 ; i >= 0 ; i--) {
for ( int j = 1 ; j <= target; j++) {
if (j >= A.get(i)) {
dp[i][j] = Math.min(
dp[i + 1 ][j],
dp[i + 1 ][j - A.get(i)] + 1 );
}
else {
dp[i][j] = dp[i + 1 ][j];
}
}
}
if (dp[ 0 ][target] >= 2001 ) {
System.out.println( "-1" );
}
else {
System.out.println(dp[ 0 ][target]);
}
}
else {
System.out.println( "-1" );
}
}
public static void main(String[] args)
{
List<Integer> A = Arrays.asList( 2 , 3 , 1 , 4 );
int N = A.size();
minOp(A, N);
}
}
|
Python
def min_op(A):
sum = 0
for num in A:
sum + = num
if sum % 2 = = 0 :
target = sum / / 2
N = len (A)
dp = [[ 0 for _ in range (target + 1 )] for _ in range (N + 1 )]
for i in range (N - 1 , - 1 , - 1 ):
for j in range (target, - 1 , - 1 ):
if j > = A[i]:
dp[i][j] = max (dp[i + 1 ][j], dp[i + 1 ][j - A[i]] + 1 )
else :
dp[i][j] = dp[i + 1 ][j]
if dp[ 0 ][target] = = 0 :
print ( "-1" )
else :
print (dp[ 0 ][target])
else :
print ( "-1" )
if __name__ = = "__main__" :
A = [ 2 , 3 , 1 , 4 ]
min_op(A)
|
C#
using System;
class GFG {
static void MinOp( int [] A, int N)
{
int sum = 0;
foreach ( var num in A) { sum += num; }
if (sum % 2 == 0) {
int target = sum / 2;
int [, ] dp = new int [N + 1, target + 1];
for ( int i = 0; i <= N; i++) {
dp[i, 0] = 0;
}
for ( int j = 1; j <= target; j++) {
dp[N, j] = 2001;
}
for ( int i = N - 1; i >= 0; i--) {
for ( int j = 1; j <= target; j++) {
if (j >= A[i]) {
dp[i, j] = Math.Min(
dp[i + 1, j],
dp[i + 1, j - A[i]] + 1);
}
else {
dp[i, j] = dp[i + 1, j];
}
}
}
if (dp[0, target] >= 2001) {
Console.WriteLine( "-1" );
}
else {
Console.WriteLine(dp[0, target]);
}
}
else {
Console.WriteLine( "-1" );
}
}
static void Main()
{
int [] A = { 2, 3, 1, 4 };
int N = A.Length;
MinOp(A, N);
}
}
|
Javascript
function minOp(A) {
const N = A.length;
let sum = 0;
for (let i = 0; i < N; i++) {
sum += A[i];
}
if (sum % 2 === 0) {
const target = sum / 2;
const dp = new Array(N + 1).fill( null ).map(() => new Array(target + 1).fill(0));
for (let j = 1; j <= target; j++) {
dp[N][j] = 2001;
}
for (let i = N - 1; i >= 0; i--) {
for (let j = 1; j <= target; j++) {
if (j >= A[i]) {
dp[i][j] = Math.min(dp[i + 1][j],
dp[i + 1][j - A[i]] + 1);
} else {
dp[i][j] = dp[i + 1][j];
}
}
}
if (dp[0][target] >= 2001) {
console.log( "-1" );
}
else {
console.log(dp[0][target]);
}
} else {
console.log( "-1" );
}
}
const A = [2, 3, 1, 4];
minOp(A);
|
Time Complexity: O(S*N), where S is the sum of the given array.
Auxiliary Space: O(S*N)
Efficient approach : Space optimization
In previous approach the current value dp[i][j] is only depend upon the current and previous row values of DP. So to optimize the space complexity we use a single 1D array to store the computations.
Implementation:
C++
#include <bits/stdc++.h>
using namespace std;
int minOp(vector< int >& A, int N)
{
int sum = 0;
for ( auto it : A) {
sum += it;
}
if (sum % 2 == 0) {
int target = sum / 2;
vector< int > dp(target + 1, 2001);
dp[0] = 0;
for ( int i = 0; i < N; i++) {
for ( int j = target; j >= A[i]; j--) {
dp[j] = min(dp[j], dp[j - A[i]] + 1);
}
}
if (dp[target] >= 2001) {
cout << "-1" << endl;
}
else {
cout << dp[target] << endl;
}
}
else {
cout << "-1" << endl;
}
}
int main()
{
vector< int > A = { 2, 3, 1, 4 };
int N = A.size();
minOp(A, N);
return 0;
}
|
Java
import java.util.Arrays;
public class Main {
static int minOp( int [] A, int N)
{
int sum = 0 ;
for ( int value : A) {
sum += value;
}
if (sum % 2 == 0 ) {
int target = sum / 2 ;
int [] dp = new int [target + 1 ];
Arrays.fill(dp, 2001 );
dp[ 0 ] = 0 ;
for ( int i = 0 ; i < N; i++) {
for ( int j = target; j >= A[i]; j--) {
dp[j]
= Math.min(dp[j], dp[j - A[i]] + 1 );
}
}
if (dp[target] >= 2001 ) {
System.out.println( "-1" );
}
else {
System.out.println(dp[target]);
}
}
else {
System.out.println( "-1" );
}
return 0 ;
}
public static void main(String[] args)
{
int [] A = { 2 , 3 , 1 , 4 };
int N = A.length;
minOp(A, N);
}
}
|
Python
def min_op(A):
N = len (A)
sum_of_elements = sum (A)
if sum_of_elements % 2 = = 0 :
target = sum_of_elements / / 2
dp = [ float ( 'inf' )] * (target + 1 )
dp[ 0 ] = 0
for i in range (N):
for j in range (target, A[i] - 1 , - 1 ):
dp[j] = min (dp[j], dp[j - A[i]] + 1 )
if dp[target] = = float ( 'inf' ):
print ( "-1" )
else :
print (dp[target])
else :
print ( "-1" )
if __name__ = = "__main__" :
A = [ 2 , 3 , 1 , 4 ]
min_op(A)
|
C#
using System;
class Program {
static void MinOp( int [] A, int N)
{
int sum = 0;
foreach ( int num in A) { sum += num; }
if (sum % 2 == 0) {
int target = sum / 2;
int [] dp = new int [target + 1];
for ( int i = 0; i <= target; i++) {
dp[i] = 2001;
}
dp[0] = 0;
for ( int i = 0; i < N; i++) {
for ( int j = target; j >= A[i]; j--) {
dp[j]
= Math.Min(dp[j], dp[j - A[i]] + 1);
}
}
if (dp[target] >= 2001) {
Console.WriteLine( "-1" );
}
else {
Console.WriteLine(dp[target]);
}
}
else {
Console.WriteLine( "-1" );
}
}
static void Main()
{
int [] A = { 2, 3, 1, 4 };
int N = A.Length;
MinOp(A, N);
}
}
|
Javascript
function minOp(A, N) {
let sum = 0;
for (let i = 0; i < N; i++) {
sum += A[i];
}
if (sum % 2 === 0) {
let target = sum / 2;
let dp = new Array(target + 1);
for (let i = 0; i <= target; i++) {
dp[i] = 2001;
}
dp[0] = 0;
for (let i = 0; i < N; i++) {
for (let j = target; j >= A[i]; j--) {
dp[j] = Math.min(dp[j], dp[j - A[i]] + 1);
}
}
if (dp[target] >= 2001) {
console.log( "-1" );
} else {
console.log(dp[target]);
}
} else {
console.log( "-1" );
}
}
const A = [2, 3, 1, 4];
const N = A.length;
minOp(A, N);
|
Time Complexity: O(S*N), where S is the sum of the given array.
Auxiliary Space: O(target), where target is S/2
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...