You are given an integer array matchsticks where matchsticks[i] is the length of the ith matchstick. You want to use all the matchsticks to make one square. You should not break any stick, but you can link them up, and each matchstick must be used exactly one time.

Return true if you can make this square and false otherwise.

solutions

backtracking with memoization

We can try to place the current matchstick at idx into any of the four sides that still have room for it. In this way, we can parametrize all four of the sides and then memoize the calls.

def makesquare(self, matchsticks: List[int]) -> bool:
	s = sum(matchsticks)
	n = len(matchsticks)
	  
	# the largest values have the least options in terms
	# of placement, so by sorting in reverse, we reduce the
	# search space from the top
	matchsticks.sort(reverse=True)
 
	if s % 4 != 0:
	return False
	  
	side_length = s // 4
	  
	@lru_cache
	def recurse(idx, s1, s2, s3, s4):
		sides = [s1, s2, s3, s4]
		  
		if idx == n:
			return len(set(sides)) == 1
 
		ans = False
		for i in range(4):
			if matchsticks[idx] + sides[i] <= side_length:
				sides[i] += matchsticks[idx]
				ans = ans or recurse(idx+1, *sides)
				sides[i] -= matchsticks[idx]
		return ans
	  
	return recurse(0, 0,0,0,0)

backtracking (greedily filling earliest side)

Instead of parametrizing all of the sides, we can just fill in the sides in order, and

def makesquare(self, matchsticks: List[int]) -> bool:
	s = sum(matchsticks)
	n = len(matchsticks)
	  
	# the largest values have the least options in terms
	# of placement, so by sorting in reverse, we reduce the
	# search space from the top
	matchsticks.sort(reverse=True)
	if s % 4 != 0:
		return False
	  
	side_length = s // 4
	sides = [0]*4
	  
	def recurse(idx):
		if idx == n:
			return len(set(sides)) == 1
 
		for i in range(4):
			if matchsticks[idx] + sides[i] <= side_length:
				sides[i] += matchsticks[idx]
				if recurse(idx+1):
					return True
				sides[i] -= matchsticks[idx]
		  
				if sides[i] == 0:
					break
		return False
	  
	return recurse(0)