回溯方法
对于所给的火柴棍数组,因题中要求“不能折断火柴”,所以需要先对数组和进行一个判断,判断是否满足整除4的初始条件。
随后,编写回溯体。
- 对于每一根火柴,拥有四种边进行选择 - 上、下、左、右。判断是否能用所有的火柴拼成正方形,即判断在遍历完数组的所有元素之后,是否满足 上边和 == 下边和 == 左边和 == 右边和。
- 然后,在纯暴力的解法下,或者我的解法下,设立一个全局变量flag,用于记录是否存在满足条件的情况。
代码如下:
boolean flag = false;
public boolean makesquare(int[] matchsticks) {
int sum = 0;
for(int i:matchsticks) {
sum+=i;
}
if(sum % 4 != 0) {
return false;
}
backTrack(matchsticks, 0, sum/4, 0, 0, 0, 0);
return flag;
}
public void backTrack(int[] matchsticks,int index,int sum,int up,int down,int left,int right) {
if(index == matchsticks.length && up == down && down == left && left == right) {
flag = true;
return;
}
if(flag) {
return;
}
if(up <= sum - matchsticks[index]) {
backTrack(matchsticks, index+1, sum, up+matchsticks[index], down, left, right);
}
if(down <= sum - matchsticks[index]) {
backTrack(matchsticks, index+1, sum, up, down+matchsticks[index], left, right);
}
if(left <= sum - matchsticks[index]) {
backTrack(matchsticks, index+1, sum, up, down, left+matchsticks[index], right);
}
if(right <= sum - matchsticks[index]) {
backTrack(matchsticks, index+1, sum, up, down, left, right+matchsticks[index]);
}
}
勉强运行出来了
剪枝的代码
public boolean makesquare(int[] matchsticks) {
int sum = 0;
for (int matchstick : matchsticks) {
sum += matchstick;
}
if (sum % 4 != 0) return false;
int target = sum / 4;
Arrays.sort(matchsticks);
return backtrack(matchsticks, target, matchsticks.length - 1, new int[4]);
}
private boolean backtrack(int[] matchsticks, int target, int index, int[] len) {
if (index == -1) {
return len[0] == len[1] && len[1] == len[2] && len[2] == len[3];
}
for (int i = 0; i < 4; i++) {
if (len[i] + matchsticks[index] > target || (i > 0 && len[i] == len[i - 1])) continue;
len[i] += matchsticks[index];
if (backtrack(matchsticks, target, index - 1, len))
return true;
len[i] -= matchsticks[index];
}
return false;
}
作者:muzhiyuan
链接:https://leetcode-cn.com/problems/matchsticks-to-square/solution/hui-su-jian-zhi-by-muzhiyuan-j0ic/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。