Maximum possible difference between two Subarrays after removing N elements from Array
Last Updated :
21 Mar, 2023
Given an array arr[] which is of 3*N size, the task is to remove N elements and divide the whole array into two equal parts such that the difference of the sum of the left subarray and right subarray should yield to maximum.
Examples:
Input: arr[] = [5, 4, 4, 2, 3, 3]
Output: 4
Explanation: The '2' elements to be removed are [4, 3].
and when you divide the array into two equal parts after the removal
left subarray= [5, 4], right subarray= [2, 3].
The Sum difference between them is (9-5) = 4
Input: arr[] = [4, 5, 6, 1, 2, 8, 7, 9, 3]
Output: 9
Approach:
Split the array into two subarrays at some point i (N <= i <= 2 * N). We remove i - N smallest elements from the first subarray, and (2 * N - i) largest elements from the second subarray. That way, for a given split, we get the largest possible sum_first, and smallest possible sum_second.
Using Max and Min heap to keep track of the smallest and largest elements, respectively. And update the difference.
Follow the below steps to Implement the Idea:
- Initialize a final_diff variable to store the maximum difference between left and right subarray after removal of N elements.
- Run a for loop from N to 2*N and arr[] into two halves left and right.
- Remove i - N smallest elements from left array and 2*N - i largest elements from right array by using Min and Max heap.
- Calculate the sum of N largest values in left array and N smallest values in right array and find out the difference between them and store it in Curr_diff variable.
- Maximize the value of final_diff with curr_diff.
- Return the value of final_diff.
Below is the implementation
C++
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
#include <unordered_map>
#include <climits>
using namespace std;
// This function returns the (1, n-1) min and max
// elements which are to be discarded from the array
vector<int> best_remove(vector<int> left, vector<int> right, int n) {
vector<int> temp;
priority_queue<int, vector<int>, greater<int>> leftHeap(left.begin(), left.end());
priority_queue<int, vector<int>, less<int>> rightHeap(right.begin(), right.end());
if (left.size() == n && right.size() > n)
{
// remove all n elements from the right side
int count = 0;
while (count < n) {
temp.push_back(rightHeap.top());
rightHeap.pop();
count++;
}
} else if (right.size() == n && left.size() > n)
{
// remove all element from the left side
int count = 0;
while (count < n) {
temp.push_back(leftHeap.top());
leftHeap.pop();
count++;
}
} else {
int x = left.size() - n;
int count = 0;
while (count < n - x) {
temp.push_back(leftHeap.top());
leftHeap.pop();
count++;
}
count = 0;
while (count < x) {
temp.push_back(rightHeap.top());
rightHeap.pop();
count++;
}
}
return temp;
}
vector<int> remove_elements(vector<int> parent, vector<int> child) {
vector<int> result;
unordered_map<int, int> childCount;
for (int i : child) {
int count = childCount[i];
childCount[i] = count + 1;
}
for (int i : parent) {
if (childCount[i] > 0) {
childCount[i]--;
} else {
result.push_back(i);
}
}
return result;
}
int max_diff(vector<int> arr, int n) {
int mid = arr.size() / 2;
int left = accumulate(arr.begin(), arr.begin() + mid, 0);
int right = accumulate(arr.begin() + mid, arr.end(), 0);
return left - right + 1;
}
int main() {
vector<int> arr = {7, 9, 5, 8, 1, 3};
int n = arr.size() / 3;
int final_max = INT_MIN;
// starting from the index 2
for (int i = n; i <= 2 * n; i++) {
vector<int> left(arr.begin(), arr.begin() + i); // dividing the left
vector<int> right(arr.begin() + i, arr.end()); // dividing the right sub array
vector<int> bestRemoveElements = best_remove(left, right, n);
vector<int> dup = arr;
vector<int> removeElements = remove_elements(dup, bestRemoveElements);
int currMax = max_diff(removeElements, n);
final_max = max(final_max, currMax)-1;
}
cout << "The maximum difference between S1 and S2 is " << final_max << endl;
return 0;
}
Java
import java.util.*;
import java.util.stream.Collectors;
public class Main {
// This function returns the (1, n-1) min and max
// elements which are to be discarded from the array
static List<Integer> best_remove(List<Integer> left, List<Integer> right, int n) {
List<Integer> temp = new ArrayList<>();
PriorityQueue<Integer> leftHeap = new PriorityQueue<>(left);
PriorityQueue<Integer> rightHeap = new PriorityQueue<>(right);
if (left.size() == n && right.size() > n)
{
// remove all n elements from the right side
temp.addAll(rightHeap.stream().sorted(Collections.reverseOrder()).limit(n).collect(Collectors.toList()));
} else if (right.size() == n && left.size() > n)
{
// remove all element from the left side
temp.addAll(leftHeap.stream().limit(n).collect(Collectors.toList()));
} else {
int x = left.size() - n;
temp.addAll(leftHeap.stream().limit(n - x).collect(Collectors.toList()));
temp.addAll(rightHeap.stream().sorted(Collections.reverseOrder()).limit(x).collect(Collectors.toList()));
}
return temp;
}
static List<Integer> remove_elements(List<Integer> parent, List<Integer> child) {
List<Integer> result = new ArrayList<>();
Map<Integer, Integer> childCount = new HashMap<>();
for (Integer i : child) {
int count = childCount.getOrDefault(i, 0);
childCount.put(i, count + 1);
}
for (Integer i : parent) {
if (childCount.containsKey(i) && childCount.get(i) > 0) {
childCount.put(i, childCount.get(i) - 1);
} else {
result.add(i);
}
}
return result;
}
static int max_diff(List<Integer> arr, int n) {
int mid = arr.size() / 2;
int left = arr.subList(0, mid).stream().mapToInt(Integer::intValue).sum();
int right = arr.subList(mid, arr.size()).stream().mapToInt(Integer::intValue).sum();
return left - right + 1;
}
public static void main(String[] args) {
List<Integer> arr = Arrays.asList(7, 9, 5, 8, 1, 3);
int n = arr.size() / 3;
int final_max = Integer.MIN_VALUE;
// starting from the index 2
for (int i = n; i <= 2 * n; i++) {
List<Integer> left = arr.subList(0, i); // dividing the left
List<Integer> right = arr.subList(i, arr.size()); // dividing the right sub array
List<Integer> bestRemoveElements = best_remove(left, right, n);
List<Integer> dup = new ArrayList<>(arr);
List<Integer> removeElements = remove_elements(dup, bestRemoveElements);
int currMax = max_diff(removeElements, n);
final_max = Math.max(final_max, currMax);
}
System.out.println("The maximum difference between S1 and S2 is " + final_max);
}
}
Python3
import copy
import heapq
from collections import Counter
# This function return the (1, n-1) min and max
# elements which are t be discarded from the array
def best_remove(left, right):
temp = []
heapq.heapify(left)
heapq.heapify(right)
if len(left) == n and len(right) > n:
# remove all n elements from the right side
temp.extend(heapq.nlargest(n, right))
elif len(right) == n and len(left) > n:
# remove all element from the left side
temp.extend(heapq.nsmallest(n, left))
else:
x = len(left) - n
temp.extend(heapq.nsmallest(x, left)+heapq.nlargest(n-x, right))
return temp
def remove_elements(parent, child):
f_s = Counter(child)
# storing all the elements of right
# part to preserve the order incase of duplicates
r_h = []
for i in parent:
if i in f_s and f_s[i] > 0:
f_s[i] -= 1
else:
r_h.append(i)
# print("after r", left + r_h)
return r_h
# Remove the child from parent
# divide the array
# sum the left and right elements
# track the curr max sum until the for loops terminates
# return the final max difference
# print(parent, n, child, m)
# print(left, right)
def max_diff(arr): # function that calculate the sum of maximum difference between two arrays
# print(arr)
mid = len(arr)//2
left = sum(arr[:mid])
right = sum(arr[mid:])
return left-right
arr = [7, 9, 5, 8, 1, 3]
n = len(arr)//3
final_max = -float("inf")
# starting from the index 2
for i in range(n, 2 * n + 1):
left = arr[:i] # dividing the left
right = arr[i:] # dividing the right sub array
# print(left, right)
# functions which returns the best elements to be removed from both sub arrays
best_remove_elements = best_remove(left, right)
# print(best_remove_elements)
dup = []
# copying the original array so that the changes might not reflect
dup = copy.deepcopy(arr)
# function that returns the array after removing the best_remove elements
remove_element = remove_elements(dup, best_remove_elements)
# print(remove_element)
# return(remove_element)
curr_max = max_diff(remove_element) # tracking the maximum
final_max = max(final_max, curr_max)
print("The maximum difference between S1 and S2 is", final_max)
C#
using System;
using System.Linq;
using System.Collections.Generic;
public class GFG {
// This function return the (1, n-1) min and max
// elements which are t be discarded from the array
static List<int> BestRemove(List<int> left, List<int> right, int n)
{
List<int> temp = new List<int>();
left.Sort();
right.Sort();
if (left.Count == n && right.Count > n)
// remove all n elements from the right side
temp.AddRange(right.OrderByDescending(x => x).Take(n));
else if (right.Count == n && left.Count > n)
// remove all element from the left side
temp.AddRange(left.OrderBy(x => x).Take(n));
else {
int x = left.Count - n;
temp.AddRange(left.OrderBy(x => x).Take(x));
temp.AddRange(right.OrderByDescending(x => x).Take(n - x));
}
return temp;
}
static List<int> RemoveElements(List<int> parent, List<int> child)
{
Dictionary<int, int> f_s = child.GroupBy(x => x).ToDictionary(g => g.Key, g => g.Count());
// storing all the elements of right
// part to preserve the order incase of duplicates
List<int> r_h = new List<int>();
foreach (int i in parent) {
if (f_s.ContainsKey(i) && f_s[i] > 0)
f_s[i] -= 1;
else
r_h.Add(i);
}
// print("after r", left + r_h)
return r_h;
}
// Remove the child from parent
// divide the array
// sum the left and right elements
// track the curr max sum until the for loops terminates
// return the final max difference
// print(parent, n, child, m)
// print(left, right)
// function that calculate the sum of maximum difference between two arrays
// print(arr)
static int GetMaxDiff(List<int> arr, int n)
{
int mid = arr.Count / 2;
List<int> left = arr.Take(mid).ToList();
List<int> right = arr.Skip(mid).ToList();
int diff = left.Sum() - right.Sum();
return diff;
}
public static void Main()
{
int[] arr = {7, 9, 5, 8, 1, 3};
int n = arr.Length / 3;
int finalMax = int.MinValue;
// starting from the index 2
for (int i = n; i <= 2 * n; i++) {
// functions which returns the best elements to be removed from both sub arrays
List<int> bestRemoveElements = BestRemove(arr.Take(i).ToList(), arr.Skip(i).ToList(), n);
// copying the original array so that the changes might not reflect
List<int> dup = new List<int>(arr);
// function that returns the array after removing the best_remove elements
List<int> removeElements = RemoveElements(dup, bestRemoveElements);
int currMax = GetMaxDiff(removeElements, n); // tracking the maximum
finalMax = Math.Max(finalMax, currMax);
}
Console.WriteLine("The maximum difference between S1 and S2 is {0}", finalMax);
}
}
// This code is contributed by Shivhack999
JavaScript
function best_remove(left, right, n) {
let temp = [];
left.sort();
right.sort();
if (left.length == n && right.length > n) {
temp.push(...right.sort((a, b) => b - a).slice(0, n));
} else if (right.length == n && left.length > n) {
temp.push(...left.sort((a, b) => a - b).slice(0, n));
} else {
let x = left.length - n;
temp.push(...left.sort((a, b) => a - b).slice(0, x));
temp.push(...right.sort((a, b) => b - a).slice(0, n - x));
}
return temp;
}
function remove_elements(parent, child) {
let f_s = child.reduce((acc, val) => {
acc[val] = (acc[val] || 0) + 1;
return acc;
}, {});
let r_h = [];
for (let i = 0; i < parent.length; i++) {
if (f_s[parent[i]] && f_s[parent[i]] > 0) {
f_s[parent[i]]--;
} else {
r_h.push(parent[i]);
}
}
return r_h;
}
function max_diff(arr, n) {
let mid = Math.floor(arr.length / 2);
let left = arr.slice(0, mid);
let right = arr.slice(mid);
let diff = left.reduce((acc, val) => acc + val, 0) - right.reduce((acc, val) => acc + val, 0);
return diff;
}
let arr = [7, 9, 5, 8, 1, 3];
let n = Math.floor(arr.length / 3);
let finalMax = Number.MIN_SAFE_INTEGER;
for (let i = n; i <= 2 * n; i++) {
let bestRemoveElements = best_remove(arr.slice(0, i), arr.slice(i), n);
let dup = [...arr];
let removeElement = remove_elements(dup, bestRemoveElements);
let currMax = max_diff(removeElement, n);
finalMax = Math.max(finalMax, currMax);
}
console.log("The maximum difference between S1 and S2 is " + finalMax);
OutputThe maximum difference between S1 and S2 is 13
Time Complexity: (N*log(N))
Auxiliary Space: O(N)
Similar Reads
Maximum subarray sum possible after removing at most K array elements Given an array arr[] of size N and an integer K, the task is to find the maximum subarray sum by removing at most K elements from the array. Examples: Input: arr[] = { -2, 1, 3, -2, 4, -7, 20 }, K = 1 Output: 26 Explanation: Removing arr[5] from the array modifies arr[] to { -2, 1, 3, -2, 4, 20 } Su
15+ min read
Minimize maximum difference between adjacent elements possible by removing a single array element Given an sorted array arr[] consisting of N elements, the task is to find the minimum of all maximum differences between adjacent elements of all arrays obtained by removal of any single array element. Examples: Input: arr[ ] = { 1, 3, 7, 8}Output: 5Explanation:All possible arrays after removing a s
6 min read
Minimize difference between maximum and minimum array elements by removing a K-length subarray Given an array arr[] consisting of N integers and an integer K, the task is to find the minimum difference between the maximum and minimum element present in the array after removing any subarray of size K. Examples: Input: arr[] = {4, 5, 8, 9, 1, 2}, K = 2Output: 4Explanation: Remove the subarray {
10 min read
Minimize difference between maximum and minimum element of all possible subarrays Given an array arr[ ] of size N, the task is to find the minimum difference between maximum and minimum elements of all possible sized subarrays of arr[ ]. Examples: Input: arr[] = { 5, 14, 7, 10 } Output: 3Explanation: {7, 10} is the subarray having max element = 10 & min element = 7, and their
5 min read
Maximum difference between group of k-elements and rest of the array. You are given an array of n elements. You have to divide the given array into two group such that one group consists exactly k elements and second group consists rest of elements. Your result must be maximum possible difference of sum of elements of these two group. Examples: Input : arr[n] = {1, 5,
7 min read