Minimize transfer operations to get the given Array sum
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++
#include <bits/stdc++.h>
using namespace std;
vector<vector< int > > minSizeSum( int a[], int n)
{
int sum = 0;
for ( int i = 0; i < n; i++)
sum += a[i];
vector<vector< int > > dp(n + 1,
vector< int >(sum + 1, 1e9));
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 (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;
}
void minOperations( int N, int M, int targetSum, int A[],
int B[])
{
vector<vector< int > > dp1 = minSizeSum(A, N),
dp2 = minSizeSum(B, M);
int sum1 = 0, sum2 = 0;
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++) {
int q = targetSum - sum1 + p;
if (q < 0 || q > sum2)
continue ;
ans = min(ans, dp1[N][p] + dp2[M][q]);
}
if (ans == 1e9)
ans = -1;
cout << ans << endl;
}
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]);
minOperations(N, M, targetSum, A, B);
return 0;
}
|
Java
import java.io.*;
class GFG {
static int [][] minSizeSum( int [] a, int n)
{
int sum = 0 ;
for ( int i = 0 ; i < n; i++) {
sum += a[i];
}
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;
}
}
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 (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;
}
static void minOperations( int N, int M, int targetSum,
int [] A, int [] B)
{
int [][] dp1 = minSizeSum(A, N);
int [][] dp2 = minSizeSum(B, M);
int sum1 = 0 , sum2 = 0 ;
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++) {
int q = targetSum - sum1 + p;
if (q < 0 || q > sum2) {
continue ;
}
ans = Math.min(ans, dp1[N][p] + dp2[M][q]);
}
if (ans == ( int )1e9) {
ans = - 1 ;
}
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;
minOperations(N, M, targetSum, A, B);
}
}
|
Python3
def minSizeSum(a, n):
sum = 0
for i in range (n):
sum + = a[i]
dp = [[ 1e9 for i in range ( sum + 1 )]
for j in range (n + 1 )]
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 (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
def minOperations(N, M, targetSum, A, B):
dp1 = minSizeSum(A, N)
dp2 = minSizeSum(B, M)
sum1 = 0
sum2 = 0
for i in range (N):
sum1 + = A[i]
for i in range (M):
sum2 + = B[i]
ans = 1e9
for p in range (sum1 + 1 ):
q = targetSum - sum1 + p
if (q < 0 or q > sum2):
continue
ans = min (ans, dp1[N][p] + dp2[M][q])
if (ans = = 1e9 ):
ans = - 1
print (ans)
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;
class GFG {
static int [, ] minSizeSum( int [] a, int n)
{
int sum = 0;
for ( int i = 0; i < n; i++) {
sum += a[i];
}
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;
}
}
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 (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;
}
static void minOperations( int N, int M, int targetSum,
int [] A, int [] B)
{
int [, ] dp1 = minSizeSum(A, N);
int [, ] dp2 = minSizeSum(B, M);
int sum1 = 0, sum2 = 0;
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++) {
int q = targetSum - sum1 + p;
if (q < 0 || q > sum2) {
continue ;
}
ans = Math.Min(ans, dp1[N, p] + dp2[M, q]);
}
if (ans == ( int )1e9) {
ans = -1;
}
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;
minOperations(N, M, targetSum, A, B);
}
}
|
Javascript
const minSizeSum = (a, n) => {
let sum = 0;
for (let i = 0; i < n; i++)
sum += a[i];
let dp = new Array(n + 1).fill(1e9).map(() => new Array(sum + 1).fill(1e9));
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 (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;
}
const minOperations = (N, M, targetSum, A, B) => {
let dp1 = minSizeSum(A, N), dp2 = minSizeSum(B, M);
let sum1 = 0, sum2 = 0;
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++) {
let q = targetSum - sum1 + p;
if (q < 0 || q > sum2)
continue ;
ans = Math.min(ans, dp1[N][p] + dp2[M][q]);
}
if (ans == 1e9)
ans = -1;
console.log(`${ans}<br/>`);
}
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);
|
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;
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;
}
void minOperations( int N, int M, int targetSum, int A[],
int B[])
{
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 ;
}
ans = min(ans, dp1[p] + dp2[q]);
}
if (ans == 1e9)
ans = -1;
cout << ans << endl;
}
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]);
minOperations(N, M, targetSum, A, B);
return 0;
}
|
Java
import java.util.Arrays;
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
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
def minOperations(N: int , M: int , targetSum: int , A: List [ int ], B: List [ int ]) - > None :
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
ans = min (ans, dp1[p] + dp2[q])
if ans = = sys.maxsize:
ans = - 1
print (ans)
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
{
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;
}
static void MinOperations( int N, int M, int targetSum, int [] A, int [] B)
{
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 ;
}
ans = Math.Min(ans, dp1[p] + dp2[q]);
}
if (ans == 1000000009)
{
ans = -1;
}
Console.WriteLine(ans);
}
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);
}
}
|
Javascript
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 minOperations(N, M, targetSum, A, B) {
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 ;
}
ans = Math.min(ans, dp1[p] + dp2[q]);
}
if (ans == 1e9) {
ans = -1;
}
console.log(ans);
}
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);
|
Time Complexity: O(N * sum)
Auxiliary Space: O(sum)
Related Articles:
Last Updated :
18 Sep, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...