Matchsticks to Square — Medium Problem & Solution
matchsticks[i] is the length of the i-th matchstick. Decide whether all of them can be laid end to end to form the four sides of one square: every stick…
- Difficulty: Medium
- Topics: Arrays, Dynamic Programming, Backtracking, Bitmask
- Asked at: Amazon, Microsoft, Meta
- 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
matchsticks[i] is the length of the i-th matchstick. Decide whether all of them can be laid end to end to form the four sides of one square: every stick must be used exactly once, sticks cannot be broken, and each side may consist of several sticks.
Return true if such a square exists, otherwise false.
Example 1
Input: matchsticks = [1,1,2,2,2]
Output: true
Explanation: Sides `1+1`, `2`, `2`, `2`.
Example 2
Input: matchsticks = [3,3,3,3,4]
Output: false
Explanation: The total, 16, means sides of length 4, and a stick of length 3 can never be topped up to exactly 4.
Example 3
Input: matchsticks = [5,5,5,5]
Output: true
Constraints
1 <= matchsticks.length <= 151 <= matchsticks[i] <= 10^8
How to solve Matchsticks to Square
Distribute the sticks into four buckets of capacity total / 4 by backtracking. Placing long sticks first and ignoring buckets that are interchangeable prunes the search to almost nothing on real inputs.
Approach
- If there are fewer than 4 sticks or
total % 4 != 0, return false. Letside = total / 4. - Sort the sticks in decreasing order; if the longest exceeds
side, return false. dfs(i): ifi == n, return true. Otherwise try each bucketjwithbucket[j] + stick[i] <= sidewhose current length differs from every earlier bucket's; add the stick, recurse, and remove it on failure.- Return
dfs(0).
Why it works
When every stick is placed and no bucket exceeds side, the four buckets sum to 4 · side, so each is exactly side — a square. Two buckets of equal current length are interchangeable for every remaining choice, so trying only one of them loses no solution.
Complexity
- Time —
O(4^n) worst case; heavily pruned in practice. A subset DP is O(2^n · n). - Space —
O(n)
Pitfalls
- Check divisibility and the longest stick before searching.
- Without sorting longest first, the search explores many hopeless partial fills.
- The total can reach 1.5 · 10^9 — it still fits in a 32-bit int, but
bucket + stickcomparisons should not overflow either.
Reference solution
Python
from typing import List
def makesquare(matchsticks: List[int]) -> bool:
n = len(matchsticks)
total = sum(matchsticks)
if n < 4 or total % 4 != 0:
return False
side = total // 4
a = sorted(matchsticks, reverse=True)
if a[0] > side:
return False
sides = [0, 0, 0, 0]
def dfs(i):
if i == n:
return True
for j in range(4):
if sides[j] + a[i] > side:
continue
if any(sides[k] == sides[j] for k in range(j)):
continue
sides[j] += a[i]
if dfs(i + 1):
return True
sides[j] -= a[i]
return False
return dfs(0)JavaScript
var makesquare = function(matchsticks) {
var n = matchsticks.length;
var total = 0;
for (var i = 0; i < n; i++) total += matchsticks[i];
if (n < 4 || total % 4 !== 0) return false;
var side = total / 4;
var a = matchsticks.slice().sort(function(x, y) { return y - x; });
if (a[0] > side) return false;
var sides = [0, 0, 0, 0];
var dfs = function(idx) {
if (idx === n) return true;
for (var j = 0; j < 4; j++) {
if (sides[j] + a[idx] > side) continue;
var dup = false;
for (var k = 0; k < j; k++) if (sides[k] === sides[j]) { dup = true; break; }
if (dup) continue;
sides[j] += a[idx];
if (dfs(idx + 1)) return true;
sides[j] -= a[idx];
}
return false;
};
return dfs(0);
};Also on the editorial tab: C, C#, C++, Go, Java, Kotlin, PHP, Ruby, Rust, Swift, TypeScript.
All 988 arrays problems · the whole catalogue
Learn the technique: Arrays · Dynamic Programming