LeetCode 473 Medium 火柴正方形 Python

 

    算法:递归/DFS

        【事实上本方法在提交的时候TLE了,但是奇葩的是官方给出的solution就是这样的并且java版本的就能通过,所以很奇怪。主要记录思路吧!】

    思路

            将列表内所有元素拼接起来能构成一个正方形。也就是说将所有元素按一定规则分配到4条边上,这4条边等长

        所以可以考虑设置4个bucket,对每个元素进行放入的测试。所有元素都放完且各条边的长度都等与sum/4的时候

        就说明有解否则无解。其实相当于将nums划分为4个互不相交的子集,且每个子集的sum都相等,等于sum/4

            直接递归所有可能很慢,所以要做一些剪枝操作:

            1. 如果 len(nums)<4,肯定构不成正方形,return False

            2. 如果sum(nums)%4 != 0,肯定构不成正方形,return False

            在dfs的过程中,用bucket记录元素累加的值,每次递归的时候是对元素进行递归,所以传递的是i,用nums[i]

        取元素,对4个桶的每个桶都进行测试放入,只有nums[i] + bucket[j] <= side时才放入并更新bucket。放入

        后对下一个元素进行递归,这里注意要根据下一层递归return的True False来定义当前层递归return的True和False

        如果下一层return的是False,用bucket[j] -= nums[i]剔除刚才对bucket[j]施加的影响,如果当前递归层整个for

        循环后都没有找到合适的放置位置,那就return False,说明没得放

 

        注意!

            这里要注意学习人家这种return 的方式,不一定非要在一开始的递归停止处才能将结果return回去,事实上这种

        return方式是从最后一层开始逐层将当前层的结果return回去,即下一层如果True,那我本层也返回True,如果下一层

        是False,并且所有的下一层递归都是False,那么我就返回False,相当于树里面,当前层是一个中间节点,我这个中间

        节点返回True 还是False取决于后续节点的return值,只要后面有一个True的我就True否则全是False我就也是False

        通过这种方式将结果带出来,不一定非要是前面做的那几种靠result列表带出的方式

    复杂度分析

        时间:O4^N,因为我们总共有N根火柴棍对于每根火柴棍,我们有4个不同的它们可能属于的子集的可能性,或者它们可能

        是正方形的一部分。

        空间:ON,对于递归解决方案,空间复杂度是所有递归调用占用的堆栈空间。这里最深层的递归调用大小为N,因此空间复

        杂度为O(N)在这个解决方案中,除了递归堆栈之外,没有其他空间了

def makesquare( nums):

    if len(nums) < 4 or sum(nums)%4 != 0:

        return False

    nums.sort(reverse=True)

    side = sum(nums)//4

    bucket = [0,0,0,0]

    def dfs(i,bucket):

        if i == len(nums):

            return bucket[0] == side and bucket[1] == side and bucket[2] == side and bucket[3] == side

        for j in range(4):

            if nums[i] + bucket[j] <= side:

                bucket[j] += nums[i]

                if dfs(i+1,bucket[:]):

                    return True

                bucket[j] -= nums[i]

        return False

    return dfs(0,bucket)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值