Minimum Cost to Connect Sticks — Medium Problem & Solution
You have sticks of the given lengths. You may connect any two of them into one stick of the combined length, at a cost equal to that combined length.
- Difficulty: Medium
- Topics: Arrays, Greedy, Heap
- Asked at: Amazon, Google, Flipkart
- Time limit: 2 s
- Memory limit: 256 MB
- Languages: JavaScript, TypeScript, Python, Java, C++, C, C#, Go, Kotlin, Swift, Rust, PHP and Ruby
Problem statement
You have sticks of the given lengths. You may connect any two of them into one stick of the combined length, at a cost equal to that combined length.
Return the minimum total cost of connecting all the sticks into a single one.
Example 1
Input: sticks = [2,4,3]
Output: 14
Explanation: Join 2 and 3 for 5, then 5 and 4 for 9 — total 14.
Example 2
Input: sticks = [1,8,3,5]
Output: 30
Example 3
Input: sticks = [5]
Output: 0
Explanation: Nothing to connect.
Constraints
1 <= sticks.length <= 50001 <= sticks[i] <= 10^4
How to solve Minimum Cost to Connect Sticks
This is Huffman's construction. Each stick's length ends up multiplied by how many joins it is carried through, so the cheapest plan joins the two shortest sticks at every step.
Approach
- Build a min-heap of the stick lengths.
- While more than one stick remains, pop the two smallest, add their sum to the total, and push the sum back.
- Return the accumulated total.
Why it works
The greedy choice is optimal by the usual exchange argument: in any optimal plan the two deepest sticks can be swapped for the two shortest without increasing the cost, so joining the shortest pair first is never wrong. A single stick costs nothing, which is why the loop condition is length > 1 rather than > 0.
Complexity
- Time —
O(n log n) - Space —
O(n)
Pitfalls
- Sorting once and joining left to right is wrong — each new stick must re-enter the ordering.
- A single stick answers 0.
- The cost of a join is the combined length, counted again at every later join it feeds into.
Reference solution
Python
from typing import List
import heapq
def connectSticks(sticks: List[int]) -> int:
heap = sticks[:]
heapq.heapify(heap)
total = 0
while len(heap) > 1:
a = heapq.heappop(heap)
b = heapq.heappop(heap)
total += a + b
heapq.heappush(heap, a + b)
return totalJavaScript
var connectSticks = function(sticks) {
var heap = sticks.slice();
var sift = function(j) {
for (;;) {
var l = 2 * j + 1, r = l + 1, s = j;
if (l < heap.length && heap[l] < heap[s]) s = l;
if (r < heap.length && heap[r] < heap[s]) s = r;
if (s === j) break;
var t = heap[s]; heap[s] = heap[j]; heap[j] = t;
j = s;
}
};
var push = function(v) {
heap.push(v);
var i = heap.length - 1;
while (i > 0) {
var p = (i - 1) >> 1;
if (heap[p] <= heap[i]) break;
var t = heap[p]; heap[p] = heap[i]; heap[i] = t;
i = p;
}
};
var pop = function() {
var top = heap[0];
var last = heap.pop();
if (heap.length > 0) { heap[0] = last; sift(0); }
return top;
};
for (var i = Math.floor(heap.length / 2) - 1; i >= 0; i--) sift(i);
var total = 0;
while (heap.length > 1) {
var a = pop(), b = pop();
total += a + b;
push(a + b);
}
return total;
};Also on the editorial tab: C, C#, C++, Go, Java, Kotlin, PHP, Ruby, Rust, Swift, TypeScript.