LeetCode: 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.

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.

Example 2:
Input: [3,3,3,3,4]
Output: false
Explanation: You cannot find a way to form a square with all the matchsticks.

Note:
The length sum of the given matchsticks is in the range of 0 to 10^9.
The length of the given matchstick array will not exceed 15.

这是一个卖火柴的小女孩的火柴们的故事。给出的数组表示每根火柴的长度,问所有的火柴能否组成一个正方形。实际上可以抽象成另一个问题:给定的数组是否可以分成4个子数组,每个子数组的数组之和相等。

首先,可以先去除一些显而易见的情况:如果数组中的元素个数小于4,一定不满足条件;如果数组中元素之和不是4的倍数,一定不满足条件;如果数组中有一个元素的值大于“边长”,一定不满足条件。

对数组中的元素遍历,声明一个数组sums,表示4个边的长度。对每一个元素,如果sums[i]+nums[pos]<=target(规定的边长),则将这个元素加进sums[i]中,如果遍历结束后,所有边长都等于target,则能够组成正方形,反之则不行。用递归来实现这个过程。Accepted的代码:

class Solution {
public:
    bool makesquare(vector<int>& nums) {
        //火柴数目小于4,不可能组成正方形
        if(nums.size()<4) return false; 
        //对数组求和
        int sum=accumulate(nums.begin(),nums.end(),0);
        //总和不是4的倍数不可能组成正方形
        if(sum%4!=0) return false;
        int target=sum/4;//边长
        //遍历一遍数组,如果有大于边长的火柴不可能组成正方形
        for(int i=0;i<nums.size();i++)
            if(nums[i]>target) return false;

        vector<int> sums(4,0);//四个边长
        //将数组从大到小排序
        sort(nums.begin(),nums.end());
        reverse(nums.begin(),nums.end());
        return dfs(nums,sums,0,target);
    }
    bool dfs(vector<int> nums,vector<int>& sums,int pos,int target)
    {
        if(sums[0]==target&&sums[1]==target&&sums[2]==target&&sums[3]==target) return true;
        if(pos==nums.size()) return false;
        for(int i=0;i<4;i++)
        {
            if(sums[i]+nums[pos]>target) continue;
            sums[i]+=nums[pos];
            if(dfs(nums,sums,pos+1,target)==true) return true;
            sums[i]-=nums[pos];
        }
        return false;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值