LeetCode_回溯_中等_473.火柴拼正方形

x33g5p2x  于2022-08-17 转载在 其他  
字(1.7k)|赞(0)|评价(0)|浏览(636)

1.题目

你将得到一个整数数组 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

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/matchsticks-to-square

2.思路

(1)回溯
此题可以看作698.划分为k个相等的子集这题的变形,如果所有的火柴棍可以拼成一个正方形,那么我们必定可以将数组 matchsticks 划分为 4 个和相等的子集,反之也必然。所以本题只需判断能否将数组 matchsticks 划分为 4 个和相等的子集即可,如果可以返回 true,否则返回 false。

3.代码实现(Java)

  1. //思路1————回溯
  2. class Solution {
  3. public boolean makesquare(int[] matchsticks) {
  4. int sum = 0;
  5. for (int matchstick : matchsticks) {
  6. sum += matchstick;
  7. }
  8. //所有火柴长度之和必须是 4 的倍数
  9. if (sum % 4 != 0) {
  10. return false;
  11. }
  12. int k = 4;
  13. //定义 k 个桶(集合),每个桶记录装入当前桶的元素之和
  14. int[] buckets = new int[k];
  15. //理论上每个桶中的元素之和为 sum / k
  16. int target = sum / k;
  17. /*
  18. (1) 对数组 matchsticks 进行降序排序,sort()默认是升序排序,但是 matchsticks 是 int[],而非
  19. Integer[],所以无法直接重写 Arrays.sort() 的比较器 Comparator 的 compare() 方法
  20. (2) 提前对 matchsticks 数组排序,把大的数字排在前面,那么大的数字会先被分配到 bucket 中,
  21. 对于之后的数字,bucket[i] + matchsticks[index] 会更大,更容易触发剪枝的 if 条件。
  22. */
  23. Arrays.sort(matchsticks);
  24. for (int i = 0, j = matchsticks.length - 1; i < j; i++, j--) {
  25. // 交换 nums[i] 和 nums[j]
  26. int temp = matchsticks[i];
  27. matchsticks[i] = matchsticks[j];
  28. matchsticks[j] = temp;
  29. }
  30. return backtrack(matchsticks, 0, buckets, target);
  31. }
  32. private boolean backtrack(int[] matchsticks, int index, int[] buckets, int target) {
  33. if (index == matchsticks.length) {
  34. //查看每个桶中的元素之和是否都为 target
  35. for (int s : buckets) {
  36. if (s != target) {
  37. return false;
  38. }
  39. }
  40. return true;
  41. }
  42. for (int i = 0; i < buckets.length; i++) {
  43. //当前桶已经装满
  44. if (buckets[i] + matchsticks[index] > target) {
  45. continue;
  46. }
  47. buckets[i] += matchsticks[index];
  48. if (backtrack(matchsticks, index + 1, buckets, target)) {
  49. return true;
  50. }
  51. buckets[i] -= matchsticks[index];
  52. }
  53. //matchsticks[index] 不能装入任何一个桶
  54. return false;
  55. }
  56. }

相关文章