【473. 火柴拼正方形】

本文介绍了如何使用回溯算法解决LeetCode上的火柴拼正方形问题。通过判断火柴总和是否能被4整除,再进行降序排列,然后运用深度优先搜索(DFS)尝试分配火柴到四条边上,最终得出是否能拼成正方形的结论。文章强调了基础算法的重要性,并提供了C++实现的代码及其运行时间与内存消耗。
摘要由CSDN通过智能技术生成

来源:力扣(LeetCode)

描述

你将得到一个整数数组 matchsticks ,其中 matchsticks[i] 是第 i 个火柴棒的长度。你要用 所有的火柴棍 拼成一个正方形。你 不能折断 任何一根火柴棒,但你可以把它们连在一起,而且每根火柴棒必须 使用一次

如果你能使这个正方形,则返回 true ,否则返回 false

示例 1:
在这里插入图片描述

输入: matchsticks = [1,1,2,2,2]
输出: true
解释: 能拼成一个边长为2的正方形,每边两根火柴。

示例 2

输入: matchsticks = [3,3,3,3,4]
输出: false
解释: 不能用所有火柴拼成一个正方形。

提示:

  • 1 <= matchsticks.length <= 15
  • 1 <= matchsticks[i] <= 108

解题思路

仔细思考这个问题,其实就是判断给定的这堆火柴,能否拼成4条一样长的边!

首先通过将所有火柴的长度相加并除以4,如果余数不为0,则显然无法拼成正方形;如果余数为0,且商记为L,则问题就转换为:如何将给定数组分成4份,且每一份的长度之和均为L!

解决这个问题最直观的办法是:一一尝试,即回溯算法。

首先进行降序排列,目的是让数字有规律,并以最大的数开始匹配减小后续操作量。而后依次尝试分组,使得分组的和为target的。

在这个过程中,只有出现无法配对成target时才会返回false,其他情况下会进行回撤操作,尝试另一种配对方式,直到找到为止。

详细注释及代码如下:

代码:

class Solution {
public:
    bool makesquare(vector<int>& matchsticks) {
        int sum=0;
        for(auto num:matchsticks){
            sum+=num;
        }

        if(sum%4!=0){
            return false;
        }
        int length=sum/4;
        //降序排列,为了从最长的火柴开始尝试
        sort(matchsticks.begin(),matchsticks.end(),greater<int>());

        vector<int> edge(4);//存储4条边的长度
        return isValid(matchsticks,edge,length,0);
    }

    //dfs(回溯算法/深度优先)
    bool isValid(vector<int>& nums,vector<int>& edge,int target,int curindex){
        //遍历完毕
        if(curindex==nums.size()){
            return true;//遍历到最后一个都没出现问题,说明满足等分
        }

        //开始尝试搭建四条边
        for(int i=0;i<edge.size();i++){
            if((edge[i]+nums[curindex])>target){
                continue;//说明第i条边已经满足,该查看下一条边了
            }

            //尝试装一下
            edge[i]+=nums[curindex];
            //dfs进行下一位,如果返回true,则说明算法通过
            if(isValid(nums,edge,target,curindex+1)){
                return true;
            }
            //回撤操作
            edge[i]-=nums[curindex];
        }
        return false;//说明上述过程无论怎么尝试都无法搭建出4条相等的边
    }
};

执行用时:172 ms, 在所有 C++ 提交中击败了31.29%的用户
内存消耗:9.7 MB, 在所有 C++ 提交中击败了20.99%的用户

总结

dfs(回溯算法/深度优先)算法可以简单理解为暴力尝试,虽然简单,但在很多情况下具有实用性,必须掌握。在日常刷题或面试中,应该首先掌握这些基本方法,再去尝试优化(比如剪枝)。

author : shining-stars

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值