持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第7天,点击查看活动详情
一、题目
LeetCode 火柴拼正方形
你将得到一个整数数组 matchsticks ,其中 matchsticks[i] 是第 i 个火柴棒的长度。你要用 所有的火柴棍 拼成一个正方形。你 不能折断 任何一根火柴棒,但你可以把它们连在一起,而且每根火柴棒必须 使用一次 。
如果你能使这个正方形,则返回 true ,否则返回 false 。
示例 1:
输入: matchsticks = [1,1,2,2,2]
输出: true
解释: 能拼成一个边长为2的正方形,每边两根火柴。
示例 2:
输入: matchsticks = [3,3,3,3,4]
输出: false
解释: 不能用所有火柴拼成一个正方形。
提示:
1 <= matchsticks.length <= 15
1 <= matchsticks[i] <= 108
二、题解
给定一个整数的数组,数组元素值表示一根火柴的长度,要求判断能否使用所有的火柴拼接成一个正方形,并且不能折断火柴,每根火柴必须使用一次。
方法一
要使用火柴拼接完成一个正方形,那就需要拼接得到四条长度相等的火柴,那么数组元素的总长度就必须为4的倍数,同时需要使用这些元素任意的组合拼接来达到四条相等的边长。首先判断如果火柴都没有4根那就完全没法组成正方形了,
然后算出火柴总长度totalLen,如果不满足可以平均分配四条边的就没法组成正方形。然后我们需要记录4条边的长度,然后将火柴长度放置到边长上,并且保持刚好组合为边长的长度,当所以火柴都放置了,并且边长也都可以组合成正方形就是符合的,为了方便枚举,先给火柴长度排序,当然需要从大到小来排序的。然后就行dfs递归搜索,递归需要index记录某一根火柴,枚举其能否放入边长中来组合,同样的需要记录正方形的四条边长,这里就用square数组的四个元素来记录,然后遍历没一根火柴,尝试放入边长中拼接正方形。
三、代码
方法一 Java代码
class Solution {
int[] ms;
int sideLen;
public boolean makesquare(int[] matchsticks) {
if (matchsticks.length < 4) {
return false;
}
int totalLen = Arrays.stream(matchsticks).sum();
if (totalLen % 4 != 0) {
return false;
}
Arrays.sort(matchsticks);
for (int i = 0, j = matchsticks.length - 1; i < j; i++, j--) {
int temp = matchsticks[i];
matchsticks[i] = matchsticks[j];
matchsticks[j] = temp;
}
ms = matchsticks;
sideLen = totalLen / 4;
int[] square = new int[4];
return dfs(0, square);
}
public boolean dfs(int index, int[] square) {
if (index == ms.length) {
return true;
}
for (int i = 0; i < square.length; i++) {
square[i] += ms[index];
if (square[i] <= sideLen && dfs(index + 1, square)) {
return true;
}
square[i] -= ms[index];
}
return false;
}
}
时间复杂度:O(4^n),枚举每根火柴应该放置的边。
空间复杂度:O(n),递归使用的栈空间。