LeetCode 473. 火柴拼正方形

本文探讨了如何利用深度优先搜索算法解决一个经典的拼图问题:使用特定长度的火柴拼成一个正方形。通过详细解析算法思路和步骤,文章提供了一个清晰的解决方案,包括输入输出示例和代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

还记得童话《卖火柴的小女孩》吗?现在,你知道小女孩有多少根火柴,请找出一种能使用所有火柴拼成一个正方形的方法。不能折断火柴,可以把火柴连接起来,并且每根火柴都要用到。

输入为小女孩拥有火柴的数目,每根火柴用其长度表示。输出即为是否能用所有的火柴拼成正方形。

示例 1:

输入: [1,1,2,2,2]
输出: true

解释: 能拼成一个边长为2的正方形,每边两根火柴。

示例 2:

输入: [3,3,3,3,4]
输出: false

解释: 不能用所有火柴拼成一个正方形。

注意:

  1. 给定的火柴长度和在 0 到 10^9之间。
  2. 火柴数组的长度不超过15。

问题分析

此题用DFS。先算出正方形每个边应该的长度target,然后将给定数组nums由大到小排序,一会儿火柴是按照由长到短的顺序放置于4个边中的。然后创建一个含有4个元素的数组sides,初始值为0,里面保存着已经放置在4个边里的火柴。变量position代表接下来该放置哪根火柴,初始值为0。接下来我们调用dfs函数:dfs(0, sides, target, nums),该函数返回以当前传入参数的状态下,接下来继续放置火柴最终能否使数组sides中的各元素都等于target。在dfs函数中,我们把接下来要放置的nums[position]这根火柴依次放置于4个边中,想放置于某一边先判断如果放进去那么边长是否会超过target,如果会超过,那么继续试下一个边;如果没超过,那么将该火柴放入这个边中(更新sides[i]),然后我们以当前状态调用dfs函数,如果dfs返回true,那么说明接下来继续放置火柴最终能使数组sides中的各元素都等于target,所以我们返回true。如果没返回true,说明将该火柴放入sides[i]是行不通的,所以我们接下来打算换个边放入试试,在这之前,我们要把这根火柴从这个边拿出来(sides[i] -= nums[position])。如果这根火柴放到哪个边里都行不通,那么我们就返回false。递归基是当全部火柴都已放置进了各边中时,这时各个边的长度一定都等于target,所以返回true。

代码实现

class Solution {
public:
    bool makesquare(vector<int>& nums) {
        if(nums.size() < 4)
            return false;
        int sum = 0;
        for(int i : nums)
            sum += i;
        if(sum % 4 != 0)
            return false;
        sort(nums.rbegin(), nums.rend());
        int target = sum / 4;
        vector<int> sides(4, 0);
        return dfs(0, sides, target, nums);
    }
    
    bool dfs(int position, vector<int>& sides, int& target, vector<int>& nums){
        if(position == nums.size())
            return true;
        for(int i = 0; i < 4; i++){
            if(sides[i] + nums[position] > target)
                continue;
            sides[i] += nums[position];
            if(dfs(position + 1, sides, target, nums))
                return true;
            sides[i] -= nums[position];
        }
        return false;
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值