Minimize remaining array element by removing pairs and replacing them by their absolute difference
Given an array arr[] consisting of N positive integers, the task is to minimize the remaining array element that can be obtained by repeatedly removing a pair of array elements and replacing them by their absolute difference.
Examples:
Input: arr[] ={ 2, 7, 4, 1, 8, 1 }
Output: 1
Explanation:
Removing the pair (arr[0], arr[2]) from arr[] and inserting abs(arr[0] – arr[2]) into arr[] modifies arr[] to { 2, 7, 1, 8, 1 }.
Removing the pair (arr[1], arr[3]) from arr[] and inserting abs(arr[1] – arr[3]) into arr[] modifies arr[] to { 2, 1, 1, 1 }.
Removing the pair (arr[0], arr[1]) from arr[] and inserting abs(arr[0] – arr[1]) into arr[] modifies arr[] to { 1, 1, 1 }.
Removing the pair (arr[0], arr[1]) from arr[] modifies arr[] to { 1 }.
Therefore, the required output is 1.
Input: arr[] = { 1, 1, 4, 2, 2 }
Output: 0
Approach: The problem can be solved using Dynamic programming based on the following observations:
Consider an array arr[] = { a, b, c, d }.
If a > b, then removing the pair (a, b) modifies arr[] to { a – b, c, d }
If c > d, then removing the pair (c, d) modifies arr[] to { a – b, c – d }
If (a – b) > (c – d), then removing the pair (a – b, c – d) modifies arr[] to { (a + d) – (b + c) }
From the above observation, it can be observed that the problem is to partition the array into two subsets with minimum difference of their subset sums.
Following is the recurrence relation:
min_diff(i, sum) = min(min_diff(i – 1, sum + arr[i – 1]), min_diff(i – 1, sum))
where, i : index of array elements
sum : sum of elements of the first subset
Follow the steps below to solve the problem:
- Initialize a 2D array, say dp[][], to store the minimum difference of subset sums that can be obtained upto the ith element.
- Use the above recurrence relation and calculate the value of dp[N][sum].
- Finally, print the value of dp[N][sum] as the required sum.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int smallestLeft( int arr[], int total,
int sum, int i, vector<vector< int > > &dp)
{
if (i == 0) {
return abs (total - 2 * sum);
}
if (dp[i][sum] != -1)
return dp[i][sum];
int X = smallestLeft(arr, total,
sum + arr[i - 1], i - 1, dp);
int Y = smallestLeft(arr, total,
sum, i - 1, dp);
return dp[i][sum] = min(X, Y);
}
int UtilSmallestElement( int arr[], int N)
{
int total = 0;
for ( int i = 0; i < N; i++) {
total += arr[i];
}
vector<vector< int > > dp(N + 1,
vector< int >(total, -1));
cout<< smallestLeft(arr, total,
0, N, dp);
}
int main()
{
int arr[] = { 2, 7, 4, 1, 8, 1 };
int N = sizeof (arr) / sizeof (arr[0]);
UtilSmallestElement(arr, N);
return 0;
}
|
Java
import java.util.*;
import java.lang.*;
class GFG
{
static int smallestLeft( int arr[], int total,
int sum, int i, int [][] dp)
{
if (i == 0 )
{
return Math.abs(total - 2 * sum);
}
if (dp[i][sum] != - 1 )
return dp[i][sum];
int X = smallestLeft(arr, total,
sum + arr[i - 1 ], i - 1 , dp);
int Y = smallestLeft(arr, total,
sum, i - 1 , dp);
return dp[i][sum] = Math.min(X, Y);
}
static void UtilSmallestElement( int arr[], int N)
{
int total = 0 ;
for ( int i = 0 ; i < N; i++)
{
total += arr[i];
}
int [][] dp = new int [N + 1 ][total];
for ( int [] k:dp)
Arrays.fill(k, - 1 );
System.out.println(smallestLeft(arr, total,
0 , N, dp));
}
public static void main (String[] args)
{
int arr[] = { 2 , 7 , 4 , 1 , 8 , 1 };
int N = arr.length;
UtilSmallestElement(arr, N);
}
}
|
Python3
def smallestLeft( arr, total, sum , i, dp):
if (i = = 0 ):
return abs (total - 2 * sum )
if (dp[i][ sum ] ! = - 1 ):
return dp[i][ sum ]
X = smallestLeft(arr, total, sum + arr[i - 1 ], i - 1 , dp)
Y = smallestLeft(arr, total, sum , i - 1 , dp)
dp[i][ sum ] = min (X, Y)
return dp[i][ sum ]
def UtilSmallestElement(arr, N):
total = 0
for i in range ( 0 , N):
total + = arr[i]
dp = [[ - 1 for y in range (total)] for x in range (N + 1 )]
print (smallestLeft(arr, total, 0 , N, dp))
arr = [ 2 , 7 , 4 , 1 , 8 , 1 ]
N = len (arr)
UtilSmallestElement(arr, N)
|
C#
using System;
public class GFG
{
static int smallestLeft( int []arr, int total,
int sum, int i, int [,] dp)
{
if (i == 0)
{
return Math.Abs(total - 2 * sum);
}
if (dp[i,sum] != -1)
return dp[i,sum];
int X = smallestLeft(arr, total,
sum + arr[i - 1], i - 1, dp);
int Y = smallestLeft(arr, total,
sum, i - 1, dp);
return dp[i,sum] = Math.Min(X, Y);
}
static void UtilSmallestElement( int []arr, int N)
{
int total = 0;
for ( int i = 0; i < N; i++)
{
total += arr[i];
}
int [,] dp = new int [N + 1,total];
for ( int i = 0; i < N + 1; i++)
{
for ( int j = 0; j < total; j++)
{
dp[i, j] = -1;
}
}
Console.WriteLine(smallestLeft(arr, total,
0, N, dp));
}
public static void Main(String[] args)
{
int []arr = { 2, 7, 4, 1, 8, 1 };
int N = arr.Length;
UtilSmallestElement(arr, N);
}
}
|
Javascript
<script>
let M = 6;
let N = 7;
function smallestLeft(arr, total,
sum, i, dp)
{
if (i == 0)
{
return Math.abs(total - 2 * sum);
}
if (dp[i][sum] != -1)
return dp[i][sum];
let X = smallestLeft(arr, total,
sum + arr[i - 1], i - 1, dp);
let Y = smallestLeft(arr, total,
sum, i - 1, dp);
return dp[i][sum] = Math.min(X, Y);
}
function UtilSmallestElement(arr, N)
{
let total = 0;
for (let i = 0; i < N; i++)
{
total += arr[i];
}
let dp = new Array(N + 1);
for ( var i = 0; i < dp.length; i++) {
dp[i] = new Array(2);
}
for ( var i = 0; i < dp.length; i++) {
for ( var j = 0; j < dp.length; j++) {
dp[i][j] = 1;
}
}
document.write(smallestLeft(arr, total,
0, N, dp));
}
let arr = [ 2, 7, 4, 1, 8, 1 ];
let n = arr.length;
UtilSmallestElement(arr, n);
</script>
|
Time Complexity: O(N * sum), where sum is the sum of array elements
Auxiliary space: O(N * sum)
Space optimized Approach: To optimize the above approach, the idea is to use tabulation method. Follow the steps below to solve the problem:
- Initialize an array, say dp[], where dp[i] checks if the sum i can be obtained as the sum of a subset of the given array.
- Traverse the array and calculate the sum of array elements and store it in a variable, say totalSum.
- Using the above recurrence relation, find the closest value of (totalSum] / 2), say X, such that dp[X] is true.
- Finally, print the value of (totalSum – 2 * X).
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int SmallestElementLeft( int arr[], int N)
{
int totalSum = 0;
for ( int i = 0; i < N; i++) {
totalSum += arr[i];
}
int req = totalSum / 2;
bool dp[req + 1];
memset (dp, false , sizeof (dp));
dp[0] = true ;
int reach = 0;
for ( int i = 0; i < N; i++) {
for ( int j = req; j - arr[i] >= 0; j--) {
dp[j] = dp[j] || dp[j - arr[i]];
if (dp[j]) {
reach = max(reach, j);
}
}
}
return totalSum - (2 * reach);
}
int main()
{
int arr[] = { 2, 2, 2 };
int N = sizeof (arr) / sizeof (arr[0]);
cout<< SmallestElementLeft(arr, N);
return 0;
}
|
Java
import java.util.*;
class GFG{
static int SmallestElementLeft( int arr[], int N)
{
int totalSum = 0 ;
for ( int i = 0 ; i < N; i++)
{
totalSum += arr[i];
}
int req = totalSum / 2 ;
boolean [] dp = new boolean [req + 1 ];
Arrays.fill(dp, false );
dp[ 0 ] = true ;
int reach = 0 ;
for ( int i = 0 ; i < N; i++)
{
for ( int j = req; j - arr[i] >= 0 ; j--)
{
dp[j] = dp[j] || dp[j - arr[i]];
if (dp[j])
{
reach = Math.max(reach, j);
}
}
}
return totalSum - ( 2 * reach);
}
public static void main(String[] args)
{
int arr[] = { 2 , 2 , 2 };
int N = arr.length;
System.out.print(SmallestElementLeft(arr, N));
}
}
|
Python3
def SmallestElementLeft(arr, N):
totalSum = 0
for i in range (N):
totalSum + = arr[i]
req = totalSum / / 2
dp = [ False for i in range (req + 1 )]
dp[ 0 ] = True
reach = 0
for i in range (N):
j = req
while j> = arr[i]:
dp[j] = dp[j] or dp[j - arr[i]]
if (dp[j]):
reach = max (reach, j)
j - = 1
return totalSum - ( 2 * reach)
if __name__ = = '__main__' :
arr = [ 2 , 2 , 2 ]
N = len (arr)
print (SmallestElementLeft(arr, N))
|
C#
using System;
class GFG
{
static int SmallestElementLeft( int [] arr, int N)
{
int totalSum = 0;
for ( int i = 0; i < N; i++)
{
totalSum += arr[i];
}
int req = totalSum / 2;
bool [] dp = new bool [req + 1];
for ( int i = 0; i < req + 1; i++)
{
dp[i] = false ;
}
dp[0] = true ;
int reach = 0;
for ( int i = 0; i < N; i++)
{
for ( int j = req; j - arr[i] >= 0; j--)
{
dp[j] = dp[j] || dp[j - arr[i]];
if (dp[j])
{
reach = Math.Max(reach, j);
}
}
}
return totalSum - (2 * reach);
}
public static void Main()
{
int [] arr = { 2, 2, 2 };
int N = arr.Length;
Console.Write(SmallestElementLeft(arr, N));
}
}
|
Javascript
<script>
function SmallestElementLeft(arr , N)
{
var totalSum = 0;
for (i = 0; i < N; i++) {
totalSum += arr[i];
}
var req = totalSum / 2;
var dp =Array(req + 1).fill( false );
dp[0] = true ;
var reach = 0;
for (i = 0; i < N; i++) {
for (j = req; j - arr[i] >= 0; j--) {
dp[j] = dp[j] || dp[j - arr[i]];
if (dp[j]) {
reach = Math.max(reach, j);
}
}
}
return totalSum - (2 * reach);
}
var arr = [ 2, 2, 2 ];
var N = arr.length;
document.write(SmallestElementLeft(arr, N));
</script>
|
Output:
2
Time Complexity: O(N * sum), where sum is the sum of array elements
Auxiliary space: O(sum)
Last Updated :
04 Sep, 2021
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...