思路分析:
-
降序排序: 对输入的火柴棍数组进行降序排序,目的是优先处理较长的火柴棍,以提高深度优先搜索的效率。
-
总长度判断: 计算火柴棍的总长度,如果总长度不能被4整除,那么无法构成正方形,直接返回
false
。 -
目标边长计算: 计算目标边长
bian
,即正方形的边长。因为要分成4个相等的组,所以目标边长等于总长度除以4。 -
深度优先搜索: 使用深度优先搜索(DFS)来尝试不同的组合,检查是否能够将火柴棍分成四个相等的组。递归过程中,逐个尝试将每根火柴棍放入四个组中,并在满足条件时递归调用下一层。
-
回溯操作: 在递归调用之后,进行回溯操作,将尝试过的火柴棍从当前组中移除,以便尝试其他分支。确保在不同的选择和分支上进行搜索。
-
返回结果: 如果深度优先搜索成功找到一种组合使得火柴棍能够构成正方形,返回
true
;否则,返回false
。
class Solution {
// 深度优先搜索函数
// matchsticks: 火柴棍数组
// dp: 各组的当前累积和
// x: 当前处理的火柴棍索引
// bian: 目标边长
bool dfs(vector<int>& matchsticks, vector<int>& dp, int x, int bian) {
// 如果已经处理完所有火柴棍,检查各组的累积和是否均为目标边长
if (x == matchsticks.size()) {
return dp[0] == bian && dp[1] == bian && dp[2] == bian && dp[3] == bian;
}
// 尝试将当前火柴棍放入各个组中
for (int i = 0; i < 4; i++) {
if (dp[i] + matchsticks[x] <= bian) {
dp[i] += matchsticks[x];
// 递归调用,深度优先搜索
if (dfs(matchsticks, dp, x + 1, bian)) {
return true;
}
dp[i] -= matchsticks[x]; // 回溯,将火柴棍从当前组中移除
}
}
// 无法找到合适的组合
return false;
}
public:
// 判断是否能够构成正方形
bool makesquare(vector<int>& matchsticks) {
// 将火柴棍按降序排序,优先处理较长的火柴棍
sort(matchsticks.rbegin(), matchsticks.rend());
// 计算火柴棍总长度
int total = accumulate(matchsticks.begin(), matchsticks.end(), 0);
// 如果总长度不能被4整除,无法构成正方形
if (total % 4 != 0) {
return false;
}
// 计算目标边长
int bian = total / 4;
// 初始化各组的累积和数组
vector<int> dp(4, 0);
// 调用深度优先搜索函数,判断是否能够构成正方形
return dfs(matchsticks, dp, 0, bian);
}
};