Given an integer array files[], where files[i] represents the size of the i-th sorted file, merge all the files into a single file with the minimum total computation cost.
The cost of merging two files of sizes x and y is x + y. After merging, a new file of size x + y is created, which can be merged further.
Return the minimum total cost required to merge all the files.
Examples:
Input: files[] = [2, 3, 4] Output: 14 Explanation: There are different ways to combine these files. Optimal method is given below:
Input: files[] = [2, 3, 4, 5, 6, 7] Output: 68 Explanation: Optimal way to combine these files:
[Naive Approach] Recursion (Try All Possible Merges) - O(n! * n ^ 2) Time and O(n ^ 2) Space
The idea is to try all possible pairs of files for merging and recursively find the minimum cost for the remaining files.
Working of Approach:
If only one file remains, return 0 as no more merging is needed.
Try every possible pair of files and calculate their merging cost.
Create a new array by replacing the selected pair with their combined size.
Recursively calculate the minimum cost for the remaining files.
Return the minimum total cost among all possible merging choices.
C++
#include<iostream>#include<vector>#include<climits>#include<algorithm>usingnamespacestd;// Recursively find the minimum cost of merging files.intfind(vector<int>&files){// If only one file remains, no merge is needed.if(files.size()<=1)return0;intres=INT_MAX;intn=files.size();// Try every possible pair of files.for(inti=0;i<n;i++){for(intj=i+1;j<n;j++){// Calculate the cost of merging the selected files.intcost=files[i]+files[j];// Store the remaining files after merging.vector<int>nextFiles;// Add the merged file to the new array.nextFiles.push_back(cost);// Add all files except the selected pair.for(intk=0;k<n;k++){if(k!=i&&k!=j)nextFiles.push_back(files[k]);}// Recursively calculate the remaining minimum cost.inttotalCost=cost+find(nextFiles);// Update the minimum total cost.res=min(res,totalCost);}}// Return the minimum cost among all merging choices.returnres;}intminComputation(vector<int>&files){// Start the recursive process.returnfind(files);}intmain(){vector<int>files={2,3,4};cout<<minComputation(files)<<endl;return0;}
Java
importjava.util.*;classGFG{// Recursively find the minimum cost of merging files.publicintfind(List<Integer>files){// If only one file remains, no merge is needed.if(files.size()<=1)return0;intres=Integer.MAX_VALUE;intn=files.size();// Try every possible pair of files.for(inti=0;i<n;i++){for(intj=i+1;j<n;j++){// Calculate the cost of merging the// selected files.intcost=files.get(i)+files.get(j);// Store the remaining files after merging.List<Integer>nextFiles=newArrayList<>();// Add the merged file to the new array.nextFiles.add(cost);// Add all files except the selected pair.for(intk=0;k<n;k++){if(k!=i&&k!=j)nextFiles.add(files.get(k));}// Recursively calculate the remaining// minimum cost.inttotalCost=cost+find(nextFiles);// Update the minimum total cost.res=Math.min(res,totalCost);}}// Return the minimum cost among all merging// choices.returnres;}publicintminComputation(int[]files){// Convert the array into a list.List<Integer>fileList=newArrayList<>();for(intfile:files)fileList.add(file);// Start the recursive process.returnfind(fileList);}publicstaticvoidmain(String[]args){int[]files={2,3,4};GFGob=newGFG();System.out.println(ob.minComputation(files));}}
Python
deffind(files):# If only one file remains, no merge is needed.iflen(files)<=1:return0res=float('inf')n=len(files)# Try every possible pair of files.foriinrange(n):forjinrange(i+1,n):# Calculate the cost of merging the selected files.cost=files[i]+files[j]# Store the remaining files after merging.nextFiles=[cost]# Add all files except the selected pair.forkinrange(n):ifk!=iandk!=j:nextFiles.append(files[k])# Recursively calculate the remaining minimum cost.totalCost=cost+find(nextFiles)# Update the minimum total cost.res=min(res,totalCost)# Return the minimum cost among all merging choices.returnresdefminComputation(files):# Start the recursive process.returnfind(files)if__name__=='__main__':files=[2,3,4]print(minComputation(files))
C#
usingSystem;usingSystem.Collections.Generic;publicclassGFG{// Recursively find the minimum cost of merging files.publicintFind(List<int>files){// If only one file remains, no merge is needed.if(files.Count<=1)return0;intres=int.MaxValue;intn=files.Count;// Try every possible pair of files.for(inti=0;i<n;i++){for(intj=i+1;j<n;j++){// Calculate the cost of merging the// selected files.intcost=files[i]+files[j];// Store the remaining files after merging.List<int>nextFiles=newList<int>();// Add the merged file to the new array.nextFiles.Add(cost);// Add all files except the selected pair.for(intk=0;k<n;k++){if(k!=i&&k!=j)nextFiles.Add(files[k]);}// Recursively calculate the remaining// minimum cost.inttotalCost=cost+Find(nextFiles);// Update the minimum total cost.res=Math.Min(res,totalCost);}}// Return the minimum cost among all merging// choices.returnres;}publicintminComputation(int[]files){// Convert the array into a list.List<int>fileList=newList<int>(files);// Start the recursive process.returnFind(fileList);}publicstaticvoidMain(){int[]files={2,3,4};GFGob=newGFG();Console.WriteLine(ob.minComputation(files));}}
JavaScript
functionfind(files){// If only one file remains, no merge is needed.if(files.length<=1)return0;letres=Number.MAX_SAFE_INTEGER;letn=files.length;// Try every possible pair of files.for(leti=0;i<n;i++){for(letj=i+1;j<n;j++){// Calculate the cost of merging the selected// files.letcost=files[i]+files[j];// Store the remaining files after merging.letnextFiles=[cost];// Add all files except the selected pair.for(letk=0;k<n;k++){if(k!==i&&k!==j)nextFiles.push(files[k]);}// Recursively calculate the remaining minimum// cost.lettotalCost=cost+find(nextFiles);// Update the minimum total cost.res=Math.min(res,totalCost);}}// Return the minimum cost among all merging choices.returnres;}functionminComputation(files){// Start the recursive process.returnfind(files);}// Driver Codeletfiles=[2,3,4];console.log(minComputation(files));
Output
14
[Expected Approach] Greedy using Min Heap - O(n log n) Time and O(n) Space
The idea is to always merge the two smallest files first using a min heap. This greedy strategy minimizes the total computation cost by choosing the smallest available merging cost at each step.
Why choose the two smallest?
Every merge creates a new file, and that file may be merged again. Therefore, a file's size can contribute to the cost multiple times. The earliest chosen pair, is processed most times, so we choose the smallest.
Working of Approach:
Insert all file sizes into a min heap.
Extract the two smallest files from the min heap.
Merge them and add their sum to the total cost.
Insert the newly merged file back into the min heap.
Repeat until only one file remains and return the total cost.
Let us understand with an example: Input: files[] = [2, 3, 4]
Insert all files into the min heap: [2, 3, 4], and initialize res = 0.
Extract the two smallest files, 2 and 3, merge them with cost 5, update res = 5, and insert 5 back into the heap.
Extract the two smallest files, 4 and 5, merge them with cost 9, update res = 14, and insert 9 back into the heap.
Only one file remains in the heap, so the loop ends.
Return res = 14 as the minimum total computation cost.
C++
#include<functional>#include<iostream>#include<queue>#include<vector>usingnamespacestd;intminComputation(vector<int>&files){// min heap initialized with all file sizespriority_queue<int,vector<int>,greater<int>>pq(files.begin(),files.end());intres=0;while(pq.size()>1){// pick two smallest files and mergeinta=pq.top();pq.pop();intb=pq.top();pq.pop();// cost added to res for mergingres+=a+b;pq.push(a+b);}returnres;}intmain(){vector<int>files={2,3,4};cout<<minComputation(files)<<endl;return0;}
Java
importjava.util.PriorityQueue;publicclassGFG{publicstaticintminComputation(int[]files){// Create a min heap.PriorityQueue<Integer>pq=newPriorityQueue<>();// Add all file sizes to the min heap.for(intfile:files)pq.add(file);intres=0;// Continue merging until only one file remains.while(pq.size()>1){// Pick the two smallest files.inta=pq.poll();intb=pq.poll();// Calculate the cost of merging the files.intcost=a+b;// Add the merging cost to the result.res+=cost;// Add the merged file back to the min heap.pq.add(cost);}// Return the minimum total computation cost.returnres;}publicstaticvoidmain(String[]args){int[]files={2,3,4};System.out.println(minComputation(files));}}
Python
importheapqdefminComputation(files):# min heap initialized with all file sizespq=files[:]heapq.heapify(pq)res=0whilelen(pq)>1:# pick two smallest files and mergea=heapq.heappop(pq)b=heapq.heappop(pq)# cost added to res for mergingres+=a+bheapq.heappush(pq,a+b)returnresif__name__=='__main__':files=[2,3,4]print(minComputation(files))
C#
usingSystem;publicclassGFG{// Min Heap implementation.publicclassMinHeap{privateint[]heap;privateintsize;publicMinHeap(intcapacity){heap=newint[capacity];size=0;}// Insert an element into the min heap.publicvoidAdd(intvalue){heap[size]=value;inti=size;size++;// Move the element upwards.while(i>0){intparent=(i-1)/2;if(heap[parent]<=heap[i])break;inttemp=heap[parent];heap[parent]=heap[i];heap[i]=temp;i=parent;}}// Remove and return the minimum element.publicintPoll(){intres=heap[0];size--;heap[0]=heap[size];inti=0;// Move the root downwards.while(true){intleft=2*i+1;intright=2*i+2;intsmallest=i;if(left<size&&heap[left]<heap[smallest])smallest=left;if(right<size&&heap[right]<heap[smallest])smallest=right;if(smallest==i)break;inttemp=heap[i];heap[i]=heap[smallest];heap[smallest]=temp;i=smallest;}returnres;}// Return the number of elements.publicintCount(){returnsize;}}publicintminComputation(int[]files){// Create a min heap.MinHeappq=newMinHeap(files.Length*2);// Add all file sizes to the min heap.foreach(intfileinfiles)pq.Add(file);intres=0;// Continue merging until only one file remains.while(pq.Count()>1){// Pick the two smallest files.inta=pq.Poll();intb=pq.Poll();// Calculate the cost of merging the files.intcost=a+b;// Add the merging cost to the result.res+=cost;// Add the merged file back to the min heap.pq.Add(cost);}// Return the minimum total computation cost.returnres;}publicstaticvoidMain(){int[]files={2,3,4};GFGob=newGFG();Console.WriteLine(ob.minComputation(files));}}
JavaScript
functionminComputation(files){// min heap initialized with all file sizesletpq=files.slice().sort((a,b)=>a-b);letres=0;while(pq.length>1){// pick two smallest files and mergeleta=pq.shift();letb=pq.shift();// cost added to res for mergingres+=a+b;pq.push(a+b);pq.sort((a,b)=>a-b);}returnres;}// Driver Codeletfiles=[2,3,4];console.log(minComputation(files));