Leetcode P473 Java使用DFS解决此问题
idea
首先我们要极端数组所有火柴的边长,在判断下是否符合正方形的需求。
//计算该数组的边长
int sideLength = Arrays.stream(matchsticks).sum();
//判断该边长是否符合正方形边长规范 边长必须是4的倍数
if (sideLength%4 !=0 ){
return false;
}
接下来我们要排序此数组,因为假如我们的数据为
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,102]
或者
1 1 1 1 2 2 2 2 3 3 3 3 9999
如果我们不进行sort排序对数组我们从下标为0开始,这样我们每一个边长的长度还小于(火柴的边长/4),所以每个火柴就会一直放入火柴,如1,1,1,1,2,2,2....所以我们要从大到小进行遍历,这样就可以大大的减少我们的时间复杂度,从最大的选择可以让我们剩下的边长长度比较小,这样就可以减少回溯的次数了。
dfs参数介绍
num是火柴数组,index是遍历火柴数组的下标,length是每个边长规定的长度,size是正方形四个边长的数组。
public boolean dfs(int[] num,int index,int length,int[] size){
在我们进行dfs的时候,如果我们的火柴数组遍历完成,并且每个边相等就代表已经组成了正方形,我们就可以直接返回true,否则就返回false
if (index == -1){
if (size[0] == size[1] && size[0] == size[2] && size[0] == size[3])
return true;
return false;
}
接下来我们遍历每个边长,如果当前边长A+当前火柴大于正方形要求的边长长度(火柴的边长/4)那么就跳出当前循环,
如果我们没有再次跳出循环那么就代表我们的我们边长加+当前火柴不大于正方形要求的边长长度,接下来我们就遍历下一个火柴。
当我们进行下一次回溯的时候还会一直看下一个边长是否合法,如果我们所有火柴都调用完毕了,并且size里面的所有边长都相等那么最终就会返回一个true。
if (dfs(num, index-1, length, size))
return true;
如果每一次回溯没有返回true那么我们就将这个火柴从这个边长数组里面拿出来。
size[i] -= num[index];
code
class Solution {
public boolean makesquare(int[] matchsticks) {
//计算该数组的边长
int sideLength = Arrays.stream(matchsticks).sum();
//判断该边长是否符合正方形边长规范 边长必须是4的倍数
if (sideLength% 4 !=0 ){
return false;
}
Arrays.sort(matchsticks);
return dfs(matchsticks, matchsticks.length-1, sideLength / 4 ,new int[4]);
}
public boolean dfs(int[] num,int index,int length,int[] size){
if (index == -1){
if (size[0] == size[1] && size[0] == size[2] && size[0] == size[3])
return true;
return false;
}
for (int i = 0; i < size.length; i++) {
if (size[i] + num[index] >length){
continue;
}
size[i] += num[index];
if (dfs(num, index-1, length, size))
return true;
size[i] -= num[index];
}
return false;
}
}