🧠
Greedy Using Min-Heap (Optimal Strategy)
💡 This approach uses a min-heap to always merge the two smallest sticks first, which is the key insight to minimize total cost.
Intuition
By always merging the two smallest sticks first, we keep the incremental cost as low as possible, similar to Huffman coding.
Algorithm
- Insert all sticks into a min-heap.
- While more than one stick remains, extract the two smallest sticks.
- Merge them and add the cost to total.
- Insert the merged stick back into the heap.
- Return the total cost after all merges.
💡 The heap ensures we always pick the smallest sticks efficiently, avoiding costly merges.
import heapq
def min_cost_greedy(sticks):
if len(sticks) <= 1:
return 0
heapq.heapify(sticks)
total_cost = 0
while len(sticks) > 1:
first = heapq.heappop(sticks)
second = heapq.heappop(sticks)
cost = first + second
total_cost += cost
heapq.heappush(sticks, cost)
return total_cost
# Driver code
if __name__ == '__main__':
sticks = [2, 4, 3]
print(min_cost_greedy(sticks)) # Output: 14
Line Notes
if len(sticks) <= 1:No cost if zero or one stick
heapq.heapify(sticks)Convert list into a min-heap for efficient smallest extraction
first = heapq.heappop(sticks)Extract smallest stick
second = heapq.heappop(sticks)Extract second smallest stick
cost = first + secondCalculate cost of merging two smallest sticks
total_cost += costAccumulate cost of merging two sticks
heapq.heappush(sticks, cost)Insert merged stick back into heap
return total_costReturn total accumulated cost after all merges
import java.util.*;
public class MinCostConnectSticksGreedy {
public static int minCostGreedy(int[] sticks) {
if (sticks.length <= 1) return 0;
PriorityQueue<Integer> minHeap = new PriorityQueue<>();
for (int stick : sticks) minHeap.add(stick);
int totalCost = 0;
while (minHeap.size() > 1) {
int first = minHeap.poll();
int second = minHeap.poll();
int cost = first + second;
totalCost += cost;
minHeap.add(cost);
}
return totalCost;
}
public static void main(String[] args) {
int[] sticks = {2, 4, 3};
System.out.println(minCostGreedy(sticks)); // Output: 14
}
}
Line Notes
if (sticks.length <= 1) return 0;No cost if zero or one stick
PriorityQueue<Integer> minHeap = new PriorityQueue<>();Min-heap to get smallest sticks efficiently
for (int stick : sticks) minHeap.add(stick);Add all sticks to heap
int first = minHeap.poll();Extract smallest stick
int second = minHeap.poll();Extract second smallest stick
int cost = first + second;Calculate cost of merging two smallest sticks
totalCost += cost;Accumulate cost of merging
minHeap.add(cost);Add merged stick back to heap
return totalCost;Return total accumulated cost after all merges
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
int minCostGreedy(vector<int> &sticks) {
if (sticks.size() <= 1) return 0;
priority_queue<int, vector<int>, greater<int>> minHeap(sticks.begin(), sticks.end());
int totalCost = 0;
while (minHeap.size() > 1) {
int first = minHeap.top(); minHeap.pop();
int second = minHeap.top(); minHeap.pop();
int cost = first + second;
totalCost += cost;
minHeap.push(cost);
}
return totalCost;
}
int main() {
vector<int> sticks = {2, 4, 3};
cout << minCostGreedy(sticks) << endl; // Output: 14
return 0;
}
Line Notes
if (sticks.size() <= 1) return 0;No cost if zero or one stick
priority_queue<int, vector<int>, greater<int>> minHeap(sticks.begin(), sticks.end());Min-heap initialization with sticks
int first = minHeap.top(); minHeap.pop();Extract smallest stick
int second = minHeap.top(); minHeap.pop();Extract second smallest stick
int cost = first + second;Calculate cost of merging two smallest sticks
totalCost += cost;Accumulate cost of merging
minHeap.push(cost);Add merged stick back to heap
return totalCost;Return total accumulated cost after all merges
class MinHeap {
constructor() {
this.heap = [];
}
swap(i, j) {
[this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]];
}
push(val) {
this.heap.push(val);
this.bubbleUp();
}
bubbleUp() {
let idx = this.heap.length - 1;
while (idx > 0) {
let parent = Math.floor((idx - 1) / 2);
if (this.heap[parent] <= this.heap[idx]) break;
this.swap(parent, idx);
idx = parent;
}
}
pop() {
if (this.heap.length === 1) return this.heap.pop();
const top = this.heap[0];
this.heap[0] = this.heap.pop();
this.bubbleDown();
return top;
}
bubbleDown() {
let idx = 0;
const length = this.heap.length;
while (true) {
let left = 2 * idx + 1;
let right = 2 * idx + 2;
let smallest = idx;
if (left < length && this.heap[left] < this.heap[smallest]) smallest = left;
if (right < length && this.heap[right] < this.heap[smallest]) smallest = right;
if (smallest === idx) break;
this.swap(idx, smallest);
idx = smallest;
}
}
size() {
return this.heap.length;
}
}
function minCostGreedy(sticks) {
if (sticks.length <= 1) return 0;
const minHeap = new MinHeap();
for (const stick of sticks) minHeap.push(stick);
let totalCost = 0;
while (minHeap.size() > 1) {
const first = minHeap.pop();
const second = minHeap.pop();
const cost = first + second;
totalCost += cost;
minHeap.push(cost);
}
return totalCost;
}
// Test
console.log(minCostGreedy([2,4,3])); // Output: 14
Line Notes
if (sticks.length <= 1) return 0;No cost if zero or one stick
const minHeap = new MinHeap();Create min-heap instance
for (const stick of sticks) minHeap.push(stick);Add all sticks to heap
const first = minHeap.pop();Extract smallest stick
const second = minHeap.pop();Extract second smallest stick
const cost = first + second;Calculate cost of merging two smallest sticks
totalCost += cost;Accumulate cost of merging
minHeap.push(cost);Add merged stick back to heap
return totalCost;Return total accumulated cost after all merges
TimeO(n log n) due to heap operations for n sticks
SpaceO(n) for the heap
Each merge involves two heap pops and one push, each O(log n), repeated n-1 times.
💡 For n=100,000 sticks, this approach is efficient and practical.
Interview Verdict: Accepted
This is the optimal and accepted solution for large inputs.