火柴拼正方形
- leetcode473 火柴拼正方形
- 题目描述
- 回溯算法
- 上期经典算法
leetcode473 火柴拼正方形
难度 - 中等
原题链接 - leetcode473 火柴拼正方形
题目描述
你将得到一个整数数组 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] <= 1e8
回溯算法
这个题的意思可以转换为,将数组分为四个相等的数组。
用回溯算法,进行选择。先看下回溯算法的基本流程。
废话不多说,直接上回溯算法框架,解决一个回溯问题,实际上就是一个决策树的遍历过程,站在回溯树的一个节点上,你只需要思考 3 个问题:
1.路径:也就是已经做出的选择。
2.选择列表:也就是你当前可以做的选择。
3.结束条件:也就是到达决策树底层,无法再做选择的条件。
代码框架
result = []
def backtrack(路径, 选择列表):
if 满足结束条件:
result.add(路径)
return
for 选择 in 选择列表:
做选择
backtrack(路径, 选择列表)
撤销选择
代码:
int n ,t;
int[]_nums;
public boolean makesquare(int[] nums) {
if(nums.length < 4){
return false;
}
int sum = 0;
for(int i = 0; i < nums.length;i++){
sum += nums[i];
}
if(sum % 4 != 0){
return false;
}
Arrays.sort(nums);
_nums = nums;
n = nums.length;
t = sum / 4;
return dfs(n - 1,0,0,new boolean[n]);
}
/**
*
* @param index
* @param cur 当前元素和
* @param cnt 已经凑够几个和为t的集合。
* @param vis 标记哪些元素被使用过了。
* @return
*/
boolean dfs(int index,int cur,int cnt,boolean[]vis){
if (cnt == 4){
return true;
}
if (cur == t){
return dfs(n - 1,0,cnt + 1,vis);
}
for (int i = index;i >= 0;i--){
if (vis[i] || cur + _nums[i] > t){
continue;
}
vis[i] = true;
if (dfs(i - 1,cur + _nums[i],cnt,vis)){
return true;
}
vis[i] = false;
if (cur == 0){
return false;
}
}
return false;
}
上期经典算法
leetcode292. Nim 游戏