Open In App

Minimize transfer operations to get the given Array sum

Improve
Improve
Like Article
Like
Save
Share
Report

Given two integer arrays A[] and B[] of length N and M respectively, the task is to find the minimum number of operations required such that the sum of elements in array A becomes targetSum. In one operation you can transfer an element from A[] to B[] or from B[] to A[].

Examples

Input: N = 4, M = 3, targetSum = 12,  A[] = {1, 2, 1, 4}, B[] = {5, 12, 11}
Output: 2
Explanation: We can do the following two operations
1) Transfer 1 from A[] to B[]
2) Transfer 5 from B[] to A[]
So, the array becomes 5 + 2 + 1 + 4 = 12, which is equal to the target sum.

Input: N = 4, M = 5, targetSum = 12, A[] = {7, 2, 4, 3], B[] = {8, 1, 1, 7, 9}
Output: 1
Explanation: We can do the following two operations
1) Transfer 4 from A[] to B[]
So, the array becomes 7 + 2 + 3 = 12, which is equal to the target sum.

Approach:  Implement the idea below to solve the problem:

We can reduce this problem into subproblems. Let’s say elements with sum p are transferred from array A[] to array B[] and elements with sum q are transferred from array B[] to array A[]. So, the number of operations will be minimum when we take minimum number of elements from array A[] with sum p and minimum number of elements from array B[] with sum q

This Problem can be solved by using Dynamic Programming, where we have to find minimum number of elements in an array with a given sum.

Follow the below steps to implement the idea:

  • Create two dynamic arrays (say dp1[][] and dp2[][]).
  • Let dp1[i][j] represent the minimum number of elements required in array A to make sum j till index i – 1, similarly, dp2[i][j] can also be defined for array B[] in the same way.
  • We can create dp1[][] and dp2[][] using this transformation dp[i][j] = min(dp[i – 1][j], dp[i – 1][j – a[i – 1]] + 1).
  • The final value of array A[] will be targetSum, let p be the sum removed from array A[] and q be the sum removed from array B[](added to array A). Then the total number of operations will be  dp1[N][p]+dp2[M][q].
  • Iterate from p = 0 to p = sum1 (where sum1 is the initial sum of values of array A). We know that targetSum = sum1 – p + q, then q will be targetSum – sum1 + p.
  • Answer will be minimum of all dp1[N][p] + dp2[M][q] from p = 0 to p = sum1.

Below is the implementation of the above approach.

C++




// C++ code to implement the approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to create dp1 and dp2, where
// dp[i][j] representsminimum number of
// elements required to make sum j till i-1
vector<vector<int> > minSizeSum(int a[], int n)
{
    // Calculating initial sum of array
    int sum = 0;
    for (int i = 0; i < n; i++)
        sum += a[i];
 
    // Initialising dp with 1e9
    vector<vector<int> > dp(n + 1,
                            vector<int>(sum + 1, 1e9));
 
    // 0 elements are needed to make sum 0
    for (int i = 0; i <= n; i++)
        dp[i][0] = 0;
 
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= sum; j++) {
 
            // If current element is not
            // selected number of elements will
            // be dp[i-1][j] and If current
            // element is selected number of
            // elements will be dp[i-1][j-a[i-1]]+1
            if (j < a[i - 1])
 
                dp[i][j] = dp[i - 1][j];
            else
                dp[i][j] = min(dp[i - 1][j],
                               dp[i - 1][j - a[i - 1]] + 1);
        }
    }
    return dp;
}
 
// Function to calculate Minimum Operations
void minOperations(int N, int M, int targetSum, int A[],
                   int B[])
{
    // Form Dp
    vector<vector<int> > dp1 = minSizeSum(A, N),
                         dp2 = minSizeSum(B, M);
 
    int sum1 = 0, sum2 = 0;
 
    // Calculating sum of elements of both arrays
    for (int i = 0; i < N; i++)
        sum1 += A[i];
 
    for (int i = 0; i < M; i++)
        sum2 += B[i];
 
    int ans = 1e9;
 
    for (int p = 0; p <= sum1; p++) {
 
        // targetSum = sum1-p+q
        // We calculate q from p
        int q = targetSum - sum1 + p;
 
        if (q < 0 || q > sum2)
            continue;
 
        // Number of operations
        ans = min(ans, dp1[N][p] + dp2[M][q]);
    }
    if (ans == 1e9)
        ans = -1;
 
    // Print Minimum operation Required
    cout << ans << endl;
}
 
// Driver code
int main()
{
    int N, M, targetSum = 12;
    int A[] = { 1, 2, 1, 4 };
    int B[] = { 5, 12, 11 };
    N = sizeof(A) / sizeof(A[0]);
    M = sizeof(B) / sizeof(B[0]);
 
    // Function call
    minOperations(N, M, targetSum, A, B);
 
    return 0;
}


Java




// Java code to implement the approach
import java.io.*;
class GFG {
 
  // Function to create dp1 and dp2, where
  // dp[i][j] representsminimum number of
  // elements required to make sum j till i-1
  static int[][] minSizeSum(int[] a, int n)
  {
 
    // Calculating initial sum of array
    int sum = 0;
    for (int i = 0; i < n; i++) {
      sum += a[i];
    }
 
    // Initialising dp with 1e9
    int[][] dp = new int[n + 1][sum + 1];
 
    for (int i = 0; i < n + 1; i++) {
      for (int j = 0; j < sum + 1; j++) {
        dp[i][j] = (int)1e9;
      }
    }
 
    // 0 elements are needed to make sum 0
    for (int i = 0; i <= n; i++) {
      dp[i][0] = 0;
    }
 
    for (int i = 1; i <= n; i++) {
      for (int j = 1; j <= sum; j++) {
 
        // If current element is not
        // selected number of elements will
        // be dp[i-1][j] and If current
        // element is selected number of
        // elements will be dp[i-1][j-a[i-1]]+1
        if (j < a[i - 1]) {
          dp[i][j] = dp[i - 1][j];
        }
        else {
          dp[i][j] = Math.min(
            dp[i - 1][j],
            dp[i - 1][j - a[i - 1]] + 1);
        }
      }
    }
 
    return dp;
  }
 
  // Function to calculate Minimum Operations
  static void minOperations(int N, int M, int targetSum,
                            int[] A, int[] B)
  {
    // Form Dp
    int[][] dp1 = minSizeSum(A, N);
    int[][] dp2 = minSizeSum(B, M);
 
    int sum1 = 0, sum2 = 0;
 
    // Calculating sum of elements of both arrays
    for (int i = 0; i < N; i++) {
      sum1 += A[i];
    }
 
    for (int i = 0; i < M; i++) {
      sum2 += B[i];
    }
 
    int ans = (int)1e9;
 
    for (int p = 0; p <= sum1; p++) {
 
      // targetSum = sum1-p+q
      // We calculate q from p
      int q = targetSum - sum1 + p;
 
      if (q < 0 || q > sum2) {
        continue;
      }
 
      // Number of operations
      ans = Math.min(ans, dp1[N][p] + dp2[M][q]);
    }
 
    if (ans == (int)1e9) {
      ans = -1;
    }
 
    // Print Minimum operation Required
    System.out.println(ans);
  }
 
  public static void main(String[] args)
  {
    int targetSum = 12;
    int[] A = { 1, 2, 1, 4 };
    int[] B = { 5, 12, 11 };
 
    int N = A.length;
    int M = B.length;
 
    // Function call
    minOperations(N, M, targetSum, A, B);
  }
}
 
// This code is contributed by lokeshmvs21.


Python3




# Python code to implement the approach
 
# Function to create dp1 and dp2, where
# dp[i][j] representsminimum number of
# elements required to make sum j till i-1
def minSizeSum(a, n):
 
    # Calculating initial sum of array
    sum = 0
    for i in range(n):
        sum += a[i]
 
    # Initialising dp with 1e9
    dp = [[1e9 for i in range(sum + 1)]
          for j in range(n + 1)]
 
    # 0 elements are needed to make sum 0
    for i in range(n + 1):
        dp[i][0] = 0
 
    for i in range(1, n + 1):
        for j in range(1, sum + 1):
 
            # If current element is not
            # selected number of elements will
            # be dp[i-1][j] and If current
            # element is selected number of
            # elements will be dp[i-1][j-a[i-1]]+1
            if (j < a[i - 1]):
 
                dp[i][j] = dp[i - 1][j]
            else:
                dp[i][j] = min(dp[i - 1][j],
                               dp[i - 1][j - a[i - 1]] + 1)
 
    return dp
 
# Function to calculate Minimum Operations
def minOperations(N, M, targetSum, A, B):
 
    # Form Dp
    dp1 = minSizeSum(A, N)
    dp2 = minSizeSum(B, M)
 
    sum1 = 0
    sum2 = 0
 
    # Calculating sum of elements of both arrays
    for i in range(N):
        sum1 += A[i]
 
    for i in range(M):
        sum2 += B[i]
 
    ans = 1e9
 
    for p in range(sum1 + 1):
 
        # targetSum = sum1-p+q
        # We calculate q from p
        q = targetSum - sum1 + p
 
        if (q < 0 or q > sum2):
            continue
 
        # Number of operations
        ans = min(ans, dp1[N][p] + dp2[M][q])
 
    if (ans == 1e9):
        ans = -1
 
    # Print Minimum operation Required
    print(ans)
 
 
# Driver code
if __name__ == '__main__':
 
    targetSum = 12
    A = [1, 2, 1, 4]
    B = [5, 12, 11]
    N = len(A)
    M = len(B)
 
    # Function call
    minOperations(N, M, targetSum, A, B)
 
# This code is contributed by Tapesh(tapeshdua420)


C#




// C# code to implement the approach
using System;
class GFG {
 
  // Function to create dp1 and dp2, where
  // dp[i][j] representsminimum number of
  // elements required to make sum j till i-1
  static int[, ] minSizeSum(int[] a, int n)
  {
 
    // Calculating initial sum of array
    int sum = 0;
    for (int i = 0; i < n; i++) {
      sum += a[i];
    }
 
    // Initialising dp with 1e9
    int[, ] dp = new int[n + 1, sum + 1];
 
    for (int i = 0; i < n + 1; i++) {
      for (int j = 0; j < sum + 1; j++) {
        dp[i, j] = (int)1e9;
      }
    }
 
    // 0 elements are needed to make sum 0
    for (int i = 0; i <= n; i++) {
      dp[i, 0] = 0;
    }
 
    for (int i = 1; i <= n; i++) {
      for (int j = 1; j <= sum; j++) {
 
        // If current element is not
        // selected number of elements will
        // be dp[i-1][j] and If current
        // element is selected number of
        // elements will be dp[i-1][j-a[i-1]]+1
        if (j < a[i - 1]) {
          dp[i, j] = dp[i - 1, j];
        }
        else {
          dp[i, j] = Math.Min(
            dp[i - 1, j],
            dp[i - 1, j - a[i - 1]] + 1);
        }
      }
    }
 
    return dp;
  }
 
  // Function to calculate Minimum Operations
  static void minOperations(int N, int M, int targetSum,
                            int[] A, int[] B)
  {
    // Form Dp
    int[, ] dp1 = minSizeSum(A, N);
    int[, ] dp2 = minSizeSum(B, M);
 
    int sum1 = 0, sum2 = 0;
 
    // Calculating sum of elements of both arrays
    for (int i = 0; i < N; i++) {
      sum1 += A[i];
    }
 
    for (int i = 0; i < M; i++) {
      sum2 += B[i];
    }
 
    int ans = (int)1e9;
 
    for (int p = 0; p <= sum1; p++) {
 
      // targetSum = sum1-p+q
      // We calculate q from p
      int q = targetSum - sum1 + p;
 
      if (q < 0 || q > sum2) {
        continue;
      }
 
      // Number of operations
      ans = Math.Min(ans, dp1[N, p] + dp2[M, q]);
    }
 
    if (ans == (int)1e9) {
      ans = -1;
    }
 
    // Print Minimum operation Required
    Console.WriteLine(ans);
  }
 
  public static void Main()
  {
    int targetSum = 12;
    int[] A = { 1, 2, 1, 4 };
    int[] B = { 5, 12, 11 };
 
    int N = A.Length;
    int M = B.Length;
 
    // Function call
    minOperations(N, M, targetSum, A, B);
  }
}
 
// This code is contributed by Samim Hossain Mondal.


Javascript




// JavaScript code to implement the approach
 
// Function to create dp1 and dp2, where
// dp[i][j] representsminimum number of
// elements required to make sum j till i-1
const minSizeSum = (a, n) => {
 
    // Calculating initial sum of array
    let sum = 0;
    for (let i = 0; i < n; i++)
        sum += a[i];
 
    // Initialising dp with 1e9
    let dp = new Array(n + 1).fill(1e9).map(() => new Array(sum + 1).fill(1e9));
 
    // 0 elements are needed to make sum 0
    for (let i = 0; i <= n; i++)
        dp[i][0] = 0;
 
    for (let i = 1; i <= n; i++) {
        for (let j = 1; j <= sum; j++) {
 
            // If current element is not
            // selected number of elements will
            // be dp[i-1][j] and If current
            // element is selected number of
            // elements will be dp[i-1][j-a[i-1]]+1
            if (j < a[i - 1])
 
                dp[i][j] = dp[i - 1][j];
            else
                dp[i][j] = Math.min(dp[i - 1][j],
                    dp[i - 1][j - a[i - 1]] + 1);
        }
    }
    return dp;
}
 
// Function to calculate Minimum Operations
const minOperations = (N, M, targetSum, A, B) => {
    // Form Dp
    let dp1 = minSizeSum(A, N), dp2 = minSizeSum(B, M);
 
    let sum1 = 0, sum2 = 0;
 
    // Calculating sum of elements of both arrays
    for (let i = 0; i < N; i++)
        sum1 += A[i];
 
    for (let i = 0; i < M; i++)
        sum2 += B[i];
 
    let ans = 1e9;
 
    for (let p = 0; p <= sum1; p++) {
 
        // targetSum = sum1-p+q
        // We calculate q from p
        let q = targetSum - sum1 + p;
 
        if (q < 0 || q > sum2)
            continue;
 
        // Number of operations
        ans = Math.min(ans, dp1[N][p] + dp2[M][q]);
    }
    if (ans == 1e9)
        ans = -1;
 
    // Print Minimum operation Required
    console.log(`${ans}<br/>`);
}
 
// Driver code
let N, M, targetSum = 12;
let A = [1, 2, 1, 4];
let B = [5, 12, 11];
N = A.length;
M = B.length;
 
// Function call
minOperations(N, M, targetSum, A, B);
 
// This code is contributed by rakeshsahni


Output

2






Time Complexity: O(N * sum)
Auxiliary Space: O(N * sum)

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 steps:

  • Create a 1D vector dp of size sum+1.
  • Set a base case by initializing the values of DP.
  • Now iterate over subproblems by the help of nested loop and get the current value from previous computations.
  • Initialize a variable ans to store the final answer and update it by iterating through the Dp.
  • At last return and print the final answer stored in ans if exists else return -1.

Implementation: 

C++




#include <bits/stdc++.h>
using namespace std;
 
// Function to create dp, where
// dp[j] represents the minimum number of
// elements required to make sum j till i-1
vector<int> minSizeSum(int a[], int n)
{
    int sum = 0;
    for (int i = 0; i < n; i++)
        sum += a[i];
 
    vector<int> dp(sum + 1, 1e9);
    dp[0] = 0;
    for (int i = 0; i < n; i++) {
        for (int j = sum; j >= a[i]; j--) {
            dp[j] = min(dp[j], dp[j - a[i]] + 1);
        }
    }
 
    return dp;
}
 
// Function to calculate Minimum Operations
void minOperations(int N, int M, int targetSum, int A[],
                   int B[])
{
    // Form Dp
    int sum_a = accumulate(A, A + N, 0);
    int sum_b = accumulate(B, B + M, 0);
    vector<int> dp1 = minSizeSum(A, N),
                dp2 = minSizeSum(B, M);
 
    int ans = 1e9;
    for (int p = 0; p <= sum_a; p++) {
        int q = targetSum - sum_a + p;
 
        if (q < 0 || q > sum_b) {
            continue;
        }
 
        // Number of operations
        ans = min(ans, dp1[p] + dp2[q]);
    }
    if (ans == 1e9)
        ans = -1;
 
    cout << ans << endl;
}
 
// Driver code
int main()
{
    int N, M, targetSum = 12;
    int A[] = { 1, 2, 1, 4 };
    int B[] = { 5, 12, 11 };
    N = sizeof(A) / sizeof(A[0]);
    M = sizeof(B) / sizeof(B[0]);
 
    // Function call
    minOperations(N, M, targetSum, A, B);
 
    return 0;
}


Java




import java.util.Arrays;
 
// Nikunj Sonigara
public class GFG {
 
    static int[] minSizeSum(int[] a) {
        int sum = 0;
        for (int num : a)
            sum += num;
 
        int[] dp = new int[sum + 1];
        Arrays.fill(dp, 1000000000);
        dp[0] = 0;
 
        for (int num : a) {
            for (int j = sum; j >= num; j--) {
                dp[j] = Math.min(dp[j], dp[j - num] + 1);
            }
        }
 
        return dp;
    }
 
    static void minOperations(int N, int M, int targetSum, int[] A, int[] B) {
        int sum_a = Arrays.stream(A).sum();
        int sum_b = Arrays.stream(B).sum();
        int[] dp1 = minSizeSum(A);
        int[] dp2 = minSizeSum(B);
 
        int ans = 1000000000;
        for (int p = 0; p <= sum_a; p++) {
            int q = targetSum - sum_a + p;
 
            if (q < 0 || q > sum_b) {
                continue;
            }
 
            ans = Math.min(ans, dp1[p] + dp2[q]);
        }
         
        if (ans == 1000000000)
            ans = -1;
 
        System.out.println(ans);
    }
 
    public static void main(String[] args) {
        int N, M, targetSum = 12;
        int[] A = { 1, 2, 1, 4 };
        int[] B = { 5, 12, 11 };
        N = A.length;
        M = B.length;
 
        minOperations(N, M, targetSum, A, B);
    }
}


Python3




from typing import List
import sys
 
# Function to create dp, where
# dp[j] represents the minimum number of
# elements required to make sum j till i-1
def minSizeSum(a: List[int]) -> List[int]:
    n = len(a)
    _sum = sum(a)
    dp = [sys.maxsize] * (_sum + 1)
    dp[0] = 0
    for i in range(n):
        for j in range(_sum, a[i] - 1, -1):
            dp[j] = min(dp[j], dp[j - a[i]] + 1)
    return dp
 
 
 # Function to calculate Minimum Operations
def minOperations(N: int, M: int, targetSum: int, A: List[int], B: List[int]) -> None:
     
    #  Form Dp
    sum_a = sum(A)
    sum_b = sum(B)
    dp1 = minSizeSum(A)
    dp2 = minSizeSum(B)
    ans = sys.maxsize
    for p in range(sum_a + 1):
        q = targetSum - sum_a + p
        if q < 0 or q > sum_b:
            continue
         
        # Number of operations
        ans = min(ans, dp1[p] + dp2[q])
    if ans == sys.maxsize:
        ans = -1
    print(ans)
 
# test case
if __name__ == "__main__":
    targetSum = 12
    A = [1, 2, 1, 4]
    B = [5, 12, 11]
    N = len(A)
    M = len(B)
    minOperations(N, M, targetSum, A, B)


C#




using System;
using System.Linq;
using System.Collections.Generic;
 
class GFG
{
    // Function to create dp, where dp[j] represents the minimum number of
    // elements required to make sum j till i-1
    static List<int> MinSizeSum(int[] a, int n)
    {
        int sum = a.Sum();
 
        List<int> dp = new List<int>(new int[sum + 1]);
        for (int i = 1; i <= sum; i++)
        {
            dp[i] = 1000000009;
        }
        dp[0] = 0;
 
        for (int i = 0; i < n; i++)
        {
            for (int j = sum; j >= a[i]; j--)
            {
                dp[j] = Math.Min(dp[j], dp[j - a[i]] + 1);
            }
        }
 
        return dp;
    }
 
    // Function to calculate Minimum Operations
    static void MinOperations(int N, int M, int targetSum, int[] A, int[] B)
    {
        // Form Dp
        int sum_a = A.Sum();
        int sum_b = B.Sum();
        List<int> dp1 = MinSizeSum(A, N);
        List<int> dp2 = MinSizeSum(B, M);
 
        int ans = 1000000009;
        for (int p = 0; p <= sum_a; p++)
        {
            int q = targetSum - sum_a + p;
 
            if (q < 0 || q > sum_b)
            {
                continue;
            }
 
            // Number of operations
            ans = Math.Min(ans, dp1[p] + dp2[q]);
        }
        if (ans == 1000000009)
        {
            ans = -1;
        }
 
        Console.WriteLine(ans);
    }
 
    // Driver code
    static void Main(string[] args)
    {
        int N, M, targetSum = 12;
        int[] A = { 1, 2, 1, 4 };
        int[] B = { 5, 12, 11 };
        N = A.Length;
        M = B.Length;
 
        // Function call
        MinOperations(N, M, targetSum, A, B);
    }
}


Javascript




// Function to create dp, where
// dp[j] represents the minimum number of
// elements required to make sum j till i-1
function minSizeSum(a, n) {
    let sum = 0;
    for (let i = 0; i < n; i++) {
        sum += a[i];
    }
    let dp = new Array(sum + 1).fill(1e9);
    dp[0] = 0;
    for (let i = 0; i < n; i++) {
        for (let j = sum; j >= a[i]; j--) {
            dp[j] = Math.min(dp[j], dp[j - a[i]] + 1);
        }
    }
    return dp;
}
 
// Function to calculate Minimum Operations
function minOperations(N, M, targetSum, A, B) {
 
    // Form Dp
    let sum_a = A.reduce((acc, curr) => acc + curr, 0);
    let sum_b = B.reduce((acc, curr) => acc + curr, 0);
    let dp1 = minSizeSum(A, N);
    let dp2 = minSizeSum(B, M);
    let ans = 1e9;
    for (let p = 0; p <= sum_a; p++) {
        let q = targetSum - sum_a + p;
        if (q < 0 || q > sum_b) {
            continue;
        }
        // Number of operations
        ans = Math.min(ans, dp1[p] + dp2[q]);
    }
    if (ans == 1e9) {
        ans = -1;
    }
    console.log(ans);
}
 
 
// Test case
let N, M, targetSum = 12;
let A = [1, 2, 1, 4];
let B = [5, 12, 11];
N = A.length;
M = B.length;
 
minOperations(N, M, targetSum, A, B);


Output

2






Time Complexity: O(N * sum)
Auxiliary Space: O(sum)

Related Articles:



Last Updated : 18 Sep, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads