题目:
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;
}
};