Matchsticks to Square

medium array dp backtracking bitmask

Problem

You are given an integer array matchsticks where matchsticks[i] is the length of the i-th matchstick. Use each matchstick exactly once. Return true if you can form a square.

Inputmatchsticks = [1, 1, 2, 2, 2]
Outputtrue
Sides 2, 2, 1+1, 2 each total 2.

def makesquare(matchsticks):
    total = sum(matchsticks)
    if total % 4 != 0: return False
    side = total // 4
    matchsticks.sort(reverse=True)
    if matchsticks[0] > side: return False
    sides = [0] * 4
    def dfs(i):
        if i == len(matchsticks): return all(s == side for s in sides)
        for k in range(4):
            if sides[k] + matchsticks[i] <= side:
                sides[k] += matchsticks[i]
                if dfs(i + 1): return True
                sides[k] -= matchsticks[i]
                if sides[k] == 0: break   # symmetry prune
        return False
    return dfs(0)
function makesquare(matchsticks) {
  const total = matchsticks.reduce((a, b) => a + b, 0);
  if (total % 4 !== 0) return false;
  const side = total / 4;
  matchsticks.sort((a, b) => b - a);
  if (matchsticks[0] > side) return false;
  const sides = [0, 0, 0, 0];
  function dfs(i) {
    if (i === matchsticks.length) return sides.every(s => s === side);
    for (let k = 0; k < 4; k++) {
      if (sides[k] + matchsticks[i] <= side) {
        sides[k] += matchsticks[i];
        if (dfs(i + 1)) return true;
        sides[k] -= matchsticks[i];
        if (sides[k] === 0) break;
      }
    }
    return false;
  }
  return dfs(0);
}
class Solution {
    int[] sticks; int side; int[] sides = new int[4];
    public boolean makesquare(int[] matchsticks) {
        int total = 0; for (int x : matchsticks) total += x;
        if (total % 4 != 0) return false;
        side = total / 4;
        Arrays.sort(matchsticks);
        for (int i = 0, j = matchsticks.length - 1; i < j; i++, j--) {
            int t = matchsticks[i]; matchsticks[i] = matchsticks[j]; matchsticks[j] = t;
        }
        if (matchsticks[0] > side) return false;
        sticks = matchsticks;
        return dfs(0);
    }
    boolean dfs(int i) {
        if (i == sticks.length) return sides[0] == side && sides[1] == side && sides[2] == side && sides[3] == side;
        for (int k = 0; k < 4; k++) {
            if (sides[k] + sticks[i] > side) continue;
            sides[k] += sticks[i];
            if (dfs(i + 1)) return true;
            sides[k] -= sticks[i];
            if (sides[k] == 0) break;
        }
        return false;
    }
}
class Solution {
    vector<int> sticks; int side; int sides[4] = {0};
public:
    bool makesquare(vector<int>& matchsticks) {
        int total = accumulate(matchsticks.begin(), matchsticks.end(), 0);
        if (total % 4) return false;
        side = total / 4;
        sort(matchsticks.rbegin(), matchsticks.rend());
        if (matchsticks[0] > side) return false;
        sticks = matchsticks;
        return dfs(0);
    }
    bool dfs(int i) {
        if (i == (int)sticks.size()) return sides[0] == side && sides[1] == side && sides[2] == side && sides[3] == side;
        for (int k = 0; k < 4; k++) {
            if (sides[k] + sticks[i] > side) continue;
            sides[k] += sticks[i];
            if (dfs(i + 1)) return true;
            sides[k] -= sticks[i];
            if (sides[k] == 0) break;
        }
        return false;
    }
};
Time: O(4^n) worst case, far less with pruning Space: O(n) recursion