[Leetcode] Matchsticks to Square 火柴拼方形

Matchsticks to Square

Remember the story of Little Match Girl? By now, you know exactly what
matchsticks the little match girl has, please find out a way you can
make one square by using up all those matchsticks. You should not
break any stick, but you can link them up, and each matchstick must be
used exactly one time.

Your input will be several matchsticks the girl has, represented with
their stick length. Your output will either be true or false, to
represent whether you could make one square using all the matchsticks
the little match girl has.python

Example 1: Input: [1,1,2,2,2] Output: true数组

Explanation: You can form a square with length 2, one side of the
square came two sticks with length 1.ide

给定一个数组,其中每一个数字是火柴长度。求是否可以用且只用一次每一根火柴,经过首尾相连来拼出一个正方形。优化

深度优先搜索

思路

因为正方形有四条边,该搜索其实要知足四个目标才能算成功,即四条边都用可以用火柴拼出来。想象此时咱们有个火柴队列,咱们拿出一支火柴,先尝试将它放入第一条边上,若是第一条边放得下,再拿出第二根火柴,尝试继续放在第一条边上,若是此时发现已经放不下了,就试着把它放在第二条边上,以此类推。细心的同窗可能会发现,若是第一根火柴在第一条边上都放不进去的话,后面也都不用试了,由于每条边长都同样,一个放不进去的话其余也放不进去。其实不仅是第一根火柴,因为较长的火柴较不容易放入边中,因此若是咱们先把较长的火柴放完再放较短的火柴,能帮助减小不少分叉的状况。因此这里一个优化的方法就是先将火柴排序,将长的放在前面。code

到这里你可能会疑惑,为何用完全部火柴就意味着四条边都拼完了呢?由于咱们规定了边长的目标为总长除以4,而所火柴用完时总长已经肯定即为边长的4倍,那么确定就是有四条边被拼出来了。orm

代码

class Solution:
    def makesquare(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        perimeter = sum(nums)
        if perimeter == 0 or perimeter % 4 != 0:
            return False
        sides = [perimeter // 4 for i in range(0, 4)]
        nums.sort(reverse=True) # 先试着拼较长的边,有助于减小搜索分叉
        return self.findSolution(nums, sides, 0) # 从第一根开始尝试拼出边
    
    def findSolution(self, nums, sides, pos):
        if pos == len(nums):
            return True
        for index in range(0, 4): # 对于当前这个火柴,尝试拼入上下左右四个边
            if sides[index] >= nums[pos]:
                sides[index] -= nums[pos] # 用当前火柴拼第index个边
                if self.findSolution(nums, sides, pos + 1): # 若是这个火柴被成功使用,就开始尝试拼下一根火柴
                    return True
                sides[index] += nums[pos] # 把当前火柴从第index个边中拿出来,好尝试下一条边
        return False
相关文章
相关标签/搜索