题目的意思大致如此:
给你一堆火柴棍,这里将其写为数组,[1,1,2,2,2]代表有5根火柴棍,长度分别为1,1,2,2,2,使用这5根火柴棍是否可以拼成一个正方形,火柴棍之间可以组合,也就是1,1可以拼成长度为2的火柴棍。这样的话,[1,1,2,2,2]就可以拼成一个正方形了。
思路:
1.首先考虑正方形的特点,四个边长都相等,那么可以先考虑数组中所有边长加起来是否能被4整除
2.在满足第1个条件后,可以考虑组合情况,通过不断枚举不同情况(DFS),查看是否有满足条件的解,如果有则返回,在此过程中需要对不满足的条件进行剪枝,避免无效搜索。
3.使用一个数组记录(sums)每条边的情况,也就是每次枚举时所记录的边的情况。
PS:在本题中满足条件的解是sums数组中4条数据都是一样的,即每条边的长度相同(即代码中满足条件)。而不满足的条件有如下几个:
1.已经搜索到火柴棍的最后一根火柴了,还没有得到合适解,或者火柴棍的个数根本不够4根(即代码中的边界条件)
2.所有火柴棍的长度加起来不能被4整除,肯定不满足条件
public class Solution {
//sums是当前每个边的大小 index是在数组中的位置 average是每个边的长度
public boolean robot(int[] nums, int [] sums , int index, int average){
//边界条件
if(nums.length<=3 || index>nums.length) return false;
//满足条件 搜索到了最后位置 并且sums的4个数字 每个数字都等于average
if(index==nums.length ){
if(sums[0]==average && sums[1]==average && sums[2]==average&& sums[3]==average)
return true;
else
return false;
}
//搜索
for(int i=0;i<4;i++){
if(nums[index]+sums[i]<=average){
if( i>0 && sums[i]==sums[i-1] ) continue; //边相同则跳过
//加上此根火柴
sums[i]+=nums[index];
//继续往下搜索
if(robot(nums,sums,index+1,average)) return true;
//还原
sums[i]-=nums[index];
}
}
return false;
}
public boolean makesquare(int[] nums) {
int sum=0;
for(int i=0;i<nums.length;i++){
sum+=nums[i];
}
//所有火柴棍加起来的和不能被4整除
if(sum%4!=0) return false;
int[] sums = new int[4];
return robot(nums,sums,0,sum/4);
}
}