Given n elements, you can remove any two elements from the list, note their sum, and add the sum to the list. Repeat these steps while there is more than a single element in the list. The task is to minimize the sum of these chosen sums in the end.
Examples:
Input: arr[] = {1, 4, 7, 10}
Output: 39
Explanation:
Choose 1 and 4, Sum = 0+1+4 = 5, arr[] = {5, 7, 10}
Choose 5 and 7, Sum = 5+5+7 = 17, arr[] = {12, 10}
Choose 12 and 10, Sum = 17+12+10 = 39, arr[] = {22}Input: arr[] = {1, 3, 7, 5, 6}
Output: 48
Explanation:
Choose 1 and 3, Sum = 4, arr[] = {4, 7, 5, 6}
Choose 4 and 5, Sum = 13, arr[] = {7, 6, 9}
Choose 6 and 7, Sum = 26, arr[] = {9, 13}
Choose 9 and 13, Sum = 48, arr[] = {22}
Approach:
In order to minimize the sum, the elements that get chosen at every step must the minimum elements from the list. In order to do that efficiently, a priority queue can be used. At every step, while there is more than a single element in the list, choose the minimum and the second minimum, remove them from the list add their sum to the list after updating the running sum.
Steps to solve the problem:
- initialize two variable i and sum to store the minimized sum.
- initialize the priority queue with min heap.
- iterate through the array and push all elements in the queue.
- while size of queue is greater than one:
- Pop the first minimum element from the heap.
- Pop the second minimum element from the heap.
- Add the sum of first minimum and second minimum to the total sum.
- Push the sum of first minimum and second minimum to the heap.
- return the sum.
Below is the implementation of the above approach:
// C++ implementation to Minimize the sum
// calculated by repeatedly removing any two
// elements and inserting their sum to the Array
#include<bits/stdc++.h>
using namespace std;
int getMinSum(vector<int> &arr) {
int n = arr.size(), sum = 0;
priority_queue<int, vector<int>, greater<int> > pq;
for (int i = 0; i < n; i++)
pq.push(arr[i]);
// While there are more than 1 elements
// left in the queue
while (pq.size() > 1) {
int min = pq.top();
pq.pop();
int secondMin = pq.top();
pq.pop();
sum += (min + secondMin);
// Add the sum of the minimum
// elements to the queue
pq.push(min + secondMin);
}
return sum;
}
int main() {
vector<int> arr = { 1, 4, 7, 10 };
cout << getMinSum(arr) << endl;
}
// Java implementation to Minimize the sum
// calculated by repeatedly removing any two
// elements and inserting their sum to the Array
import java.util.PriorityQueue;
class GfG {
static int getMinSum(int[] arr) {
int n = arr.length, sum = 0;
PriorityQueue<Integer> pq = new PriorityQueue<>();
for (int i = 0; i < n; i++)
pq.add(arr[i]);
// While there are more than 1 elements
// left in the queue
while (pq.size() > 1) {
int min = pq.poll();
int secondMin = pq.poll();
sum += (min + secondMin);
// Add the sum of the minimum
// elements to the queue
pq.add(min + secondMin);
}
return sum;
}
public static void main(String[] args) {
int[] arr = {1, 4, 7, 10};
System.out.println(getMinSum(arr));
}
}
# Python implementation to Minimize the sum
# calculated by repeatedly removing any two
# elements and inserting their sum to the Array
import heapq
def getMinSum(arr):
n = len(arr)
sum = 0
pq = []
for num in arr:
heapq.heappush(pq, num)
# While there are more than 1 elements
# left in the queue
while len(pq) > 1:
min = heapq.heappop(pq)
secondMin = heapq.heappop(pq)
sum += (min + secondMin)
# Add the sum of the minimum
# elements to the queue
heapq.heappush(pq, min + secondMin)
return sum
if __name__ == "__main__":
arr = [1, 4, 7, 10]
print(getMinSum(arr))
// C# implementation to Minimize the sum
// calculated by repeatedly removing any two
// elements and inserting their sum to the Array
using System;
using System.Collections.Generic;
// Custom comparator class for min heap
class minComparer : IComparer<int> {
public int Compare(int a, int b) {
if (a > b)
return 1;
else if (a < b)
return -1;
return 0;
}
}
class GfG {
static int getMinSum(int[] arr) {
int n = arr.Length, sum = 0;
PriorityQueue<int> pq = new PriorityQueue<int>(new minComparer());
for (int i = 0; i < n; i++)
pq.Enqueue(arr[i]);
// While there are more than 1 elements
// left in the queue
while (pq.Count > 1) {
int min = pq.Dequeue();
int secondMin = pq.Dequeue();
// Update the sum
sum += (min + secondMin);
// Add the sum of the minimum
// elements to the queue
pq.Enqueue(min + secondMin);
}
return sum;
}
static void Main() {
int[] arr = {1, 4, 7, 10};
Console.WriteLine(getMinSum(arr));
}
}
// Custom Priority queue
class PriorityQueue<T> {
private List<T> heap;
private IComparer<T> comparer;
public PriorityQueue(IComparer<T> comparer = null) {
this.heap = new List<T>();
this.comparer = comparer ?? Comparer<T>.Default;
}
public int Count => heap.Count;
// Enqueue operation
public void Enqueue(T item) {
heap.Add(item);
int i = heap.Count - 1;
while (i > 0) {
int parent = (i - 1) / 2;
if (comparer.Compare(heap[parent], heap[i]) <= 0)
break;
Swap(parent, i);
i = parent;
}
}
// Dequeue operation
public T Dequeue() {
if (heap.Count == 0)
throw new InvalidOperationException("Priority queue is empty.");
T result = heap[0];
int last = heap.Count - 1;
heap[0] = heap[last];
heap.RemoveAt(last);
last--;
int i = 0;
while (true) {
int left = 2 * i + 1;
if (left > last)
break;
int right = left + 1;
int minChild = left;
if (right <= last && comparer.Compare(heap[right], heap[left]) < 0)
minChild = right;
if (comparer.Compare(heap[i], heap[minChild]) <= 0)
break;
Swap(i, minChild);
i = minChild;
}
return result;
}
// Swap two elements in the heap
private void Swap(int i, int j) {
T temp = heap[i];
heap[i] = heap[j];
heap[j] = temp;
}
}
// JavaScript implementation to Minimize the sum
// calculated by repeatedly removing any two
// elements and inserting their sum to the Array
// Comparator function to compare data
function comparator(k1, k2) {
if (k1 > k2) return -1;
if (k1 < k2) return 1;
return 0;
}
class PriorityQueue {
constructor(compare) {
this.heap = [];
this.compare = compare;
}
enqueue(value) {
this.heap.push(value);
this.bubbleUp();
}
bubbleUp() {
let index = this.heap.length - 1;
while (index > 0) {
let element = this.heap[index],
parentIndex = Math.floor((index - 1) / 2),
parent = this.heap[parentIndex];
if (this.compare(element, parent) < 0) break;
this.heap[index] = parent;
this.heap[parentIndex] = element;
index = parentIndex;
}
}
dequeue() {
let max = this.heap[0];
let end = this.heap.pop();
if (this.heap.length > 0) {
this.heap[0] = end;
this.sinkDown(0);
}
return max;
}
sinkDown(index) {
let left = 2 * index + 1,
right = 2 * index + 2,
largest = index;
if (
left < this.heap.length &&
this.compare(this.heap[left], this.heap[largest]) > 0
) {
largest = left;
}
if (
right < this.heap.length &&
this.compare(this.heap[right], this.heap[largest]) > 0
) {
largest = right;
}
if (largest !== index) {
[this.heap[largest], this.heap[index]] = [
this.heap[index],
this.heap[largest],
];
this.sinkDown(largest);
}
}
isEmpty() {
return this.heap.length === 0;
}
size() {
return this.heap.length;
}
}
function getMinSum(arr) {
let n = arr.length, sum = 0;
let pq = new PriorityQueue(comparator);
for (let i = 0; i < n; i++)
pq.enqueue(arr[i]);
// While there are more than 1 elements
// left in the queue
while (pq.size() > 1) {
let min = pq.dequeue();
let secondMin = pq.dequeue();
sum += (min + secondMin);
// Add the sum of the minimum
// elements to the queue
pq.enqueue(min + secondMin);
}
return sum;
}
let arr = [1, 4, 7, 10];
console.log(getMinSum(arr));
Output
39
Time Complexity : O(n * log(n))
Auxiliary Space: O(n)