持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第21天,点击查看活动详情
题目描述
你将得到一个整数数组 matchsticks
,其中 matchsticks[i]
是第 i
个火柴棒的长度。你要用 所有的火柴棍 拼成一个正方形。你 不能折断 任何一根火柴棒,但你可以把它们连在一起,而且每根火柴棒必须 使用一次 。
如果你能使这个正方形,则返回 true
,否则返回 false
。
示例
输入: matchsticks = [1,1,2,2,2]
输出: true
解释: 能拼成一个边长为2的正方形,每边两根火柴。
输入: matchsticks = [3,3,3,3,4]
输出: false
解释: 不能用所有火柴拼成一个正方形。
提示
1 <= matchsticks.length <= 15
1 <= matchsticks[i] <= 10^8
回溯
要将整数数组中所有的火柴拼接成一个正方形,那么我们需要统计出所有火柴的总长度,且要保证正方形的四条边相等,由于火柴的长度不一,且不能将火柴折断,那么我们需要进行多次排列,计算出最终能否顺利拼成正方形。
正方形有四条边,那么同一根火柴,我们需要让它在四条边上都比较过,判断放在哪边最适合,这样的场景,可以使用回溯算法来进行实现。
class Solution {
public boolean makesquare(int[] matchsticks) {
// 得到火柴的总长度
int totalLen = Arrays.stream(matchsticks).sum();
// 如果不能平均分成4份,直接返回
if (totalLen % 4 != 0) {
return false;
}
// 排序
Arrays.sort(matchsticks);
// 回溯
int[] edges = new int[4];
return dfs(matchsticks.length - 1, matchsticks, edges, totalLen / 4);
}
public boolean dfs(int index, int[] matchsticks, int[] edges, int len) {
// 所有火柴均已使用,返回结果
if (index == -1) {
return true;
}
// 遍历四边
for (int i = 0; i < edges.length; i++) {
// 给当前的边加上火柴的长度
edges[i] += matchsticks[index];
// 条件判断是否符合长度并且已经使用完所有火柴
if (edges[i] <= len && dfs(index - 1, matchsticks, edges, len)) {
return true;
}
// 回溯
edges[i] -= matchsticks[index];
}
return false;
}
}