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


    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————回溯
    class Solution {
        public boolean makesquare(int[] matchsticks) {
            int sum = 0;
            for (int matchstick : matchsticks) {
                sum += matchstick;
            }
            //所有火柴长度之和必须是 4 的倍数
            if (sum % 4 != 0) {
                return false;
            }
            int k = 4;
            //定义 k 个桶(集合),每个桶记录装入当前桶的元素之和
            int[] buckets = new int[k];
            //理论上每个桶中的元素之和为 sum / k
            int target = sum / k;
            /*
                (1) 对数组 matchsticks 进行降序排序,sort()默认是升序排序,但是 matchsticks 是 int[],而非 
                    Integer[],所以无法直接重写 Arrays.sort() 的比较器 Comparator 的 compare() 方法
                (2) 提前对 matchsticks 数组排序,把大的数字排在前面,那么大的数字会先被分配到 bucket 中,
                    对于之后的数字,bucket[i] + matchsticks[index] 会更大,更容易触发剪枝的 if 条件。
            */
            Arrays.sort(matchsticks);
            for (int i = 0, j = matchsticks.length - 1; i < j; i++, j--) {
                // 交换 nums[i] 和 nums[j]
                int temp = matchsticks[i];
                matchsticks[i] = matchsticks[j];
                matchsticks[j] = temp;
            }
            return backtrack(matchsticks, 0, buckets, target);
        }
        
        private boolean backtrack(int[] matchsticks, int index, int[] buckets, int target) {
            if (index == matchsticks.length) {
                //查看每个桶中的元素之和是否都为 target
                for (int s : buckets) {
                    if (s != target) {
                        return false;
                    }
                }
                return true;
            }
            for (int i = 0; i < buckets.length; i++) {
                //当前桶已经装满
                if (buckets[i] + matchsticks[index] > target) {
                    continue;
                }
                buckets[i] += matchsticks[index];
                if (backtrack(matchsticks, index + 1, buckets, target)) {
                    return true;
                }
                buckets[i] -= matchsticks[index];
            }
            //matchsticks[index] 不能装入任何一个桶
            return false;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
  • 相关阅读:
    用vue实现pdf预览
    Linux2-系统自有服务防火墙与计划任务
    人工智能提示(prompt)工程入门
    2022年加氢工艺考试题模拟考试平台操作
    .NET周刊【11月第4期 2023-11-26】
    【C语言】常用的字符串处理函数
    神经网络遗传算法函数极值寻优
    Zookeeper集群安装教程
    C#WPF StackPanel布局及Border边框应用实例
    mysql 数据库链接状态确认实验
  • 原文地址:https://blog.csdn.net/weixin_43004044/article/details/126340133