Skip to content
Related Articles
Get the best out of our app
GeeksforGeeks App
Open App
geeksforgeeks
Browser
Continue

Related Articles

Minimize count of flips required to make sum of the given array equal to 0

Improve Article
Save Article
Like Article
Improve Article
Save Article
Like Article

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++




// C++ program for the above approach
 
#include <bits/stdc++.h>
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<int>& 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 make sum the array equal to 0
void minOp(vector<int>& 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<int> 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 make 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 make 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 make 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




<script>
// JavaScript program for the above approach
 
// Initialize dp[][]
let dp= [];
for(var i=0; i<2001; i++) {
    dp[i] = [];
    for(var j=0; j<2001; j++) {
        dp[i][j] = -1;
    }
}
 
// Function to find the minimum number
// of operations to make sum of A[] 0
function solve( A, i, sum, N){
    // Initialize answer
    let res = 2001;
 
    // Base case
    if (sum < 0 || (i == N && sum != 0)) {
        return 2001;
    }
 
    // Otherwise, return 0
    if (sum == 0 || i >= N) {
        dp[i][sum] = 0;
        return dp[i][sum];
    }
 
    // 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
    dp[i][sum] = res;
    return dp[i][sum];
}
 
// Function to find the minimum number
// of elements required to be flipped
// to make sum the array equal to 0
function minOp(A, N){
    let sum = 0;
 
    // Find the sum of array
    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);
 
        // No solution exists
        if (ans < 0 || ans > N) {
            document.write("-1 <br>");
        }
 
        // Otherwise
        else {
            document.write(ans,"<br>");
        }
    }
 
    // If sum is odd, no
    // subset is possible
    else {
         document.write("-1 <br>");
    }
}
 
// Driver Code
let A = [ 2, 3, 1, 4 ];
let N = A.length;
// Function Call
minOp(A, N);
</script>

Output

2

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;
 
// create DP to store previous computations
int dp[2001][2001];
 
// Function to find the minimum number
// of operations to make sum of A[] 0
void minOp(vector<int>& A, int N)
{
    int sum = 0;
 
    // Find the sum of array
    for (auto it : A) {
        sum += it;
    }
 
    if (sum % 2 == 0) {
        int target = sum / 2;
        // Initialize dp table
        for (int i = 0; i <= N; i++) {
            dp[i][0] = 0;
        }
        for (int j = 1; j <= target; j++) {
            dp[N][j] = 2001;
        }
        // Fill dp table in bottom-up manner
        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];
                }
            }
        }
 
        // No solution exists
        if (dp[0][target] >= 2001) {
            cout << "-1" << endl;
        }
 
        // Otherwise
        else {
            cout << dp[0][target] << endl;
        }
    }
    // If sum is odd, no subset is possible
    else {
        cout << "-1" << endl;
    }
}
 
int main()
{
    vector<int> A = { 2, 3, 1, 4 };
    int N = A.size();
 
    // Function Call
    minOp(A, N);
 
    return 0;
}

Output

2

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;
 
// Function to find the minimum number
// of operations to make sum of A[] 0
int minOp(vector<int>& A, int N)
{
    int sum = 0;
 
    // Find the sum of array
    for (auto it : A) {
        sum += it;
    }
 
    if (sum % 2 == 0) {
        int target = sum / 2;
        // Initialize dp table
        vector<int> dp(target + 1, 2001);
        dp[0] = 0;
 
        // Fill dp table in bottom-up manner
        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);
            }
        }
 
        // No solution exists
        if (dp[target] >= 2001) {
            cout << "-1" << endl;
        }
 
        // Otherwise
        else {
            cout << dp[target] << endl;
        }
    }
    // If sum is odd, no subset is possible
    else {
        cout << "-1" << endl;
    }
}
 
int main()
{
    vector<int> A = { 2, 3, 1, 4 };
    int N = A.size();
 
    // Function Call
    minOp(A, N);
 
    return 0;
}

Output

2

Time Complexity: O(S*N), where S is the sum of the given array.
Auxiliary Space: O(target), where target is S/2


My Personal Notes arrow_drop_up
Last Updated : 26 May, 2023
Like Article
Save Article
Similar Reads
Related Tutorials