Leetcode 473. 火柴拼正方形 (Java实现)

题目描述

题目来源

还记得童话《卖火柴的小女孩》吗?现在,你知道小女孩有多少根火柴,请找出一种能使用所有火柴拼成一个正方形的方法。不能折断火柴,可以把火柴连接起来,并且每根火柴都要用到。

输入为小女孩拥有火柴的数目,每根火柴用其长度表示。输出即为是否能用所有的火柴拼成正方形。

示例 1:

输入: [1,1,2,2,2]
输出: true

解释: 能拼成一个边长为2的正方形,每边两根火柴。
示例 2:

输入: [3,3,3,3,4]
输出: false

解释: 不能用所有火柴拼成一个正方形。
注意:

给定的火柴长度和在 0 到 10^9之间。
火柴数组的长度不超过15。

解题思路

  • 对于给定的若干根火柴,我们需要将他们分为四组
  • 每一组火柴的长度之和相同,等于所有火柴长度之和的四分之一

流程:

使用深度优先搜索,枚举出所有的分组情况,并对每一种情况,进行判断是否符合上面的情况。

我们对每一根火柴进行搜索,当搜索到第i根火柴的时候,将其放到4组中的一组,对于放置的每一种方法,继续对i+1根火柴进行递归搜索。当搜索完全部的火柴之后,判断每组的长度之和是否相同。

在进行搜索之前,我们可以将火柴的长度从大到小进行排序,方便我们先搜索较长的火柴。这样做的目的是对搜索进行剪枝,例如当火柴的长度为 [4,4,4,8]时,,排序后数组为[8,4,4,4]每条边的长度为 5,如果我们先搜索长度为 8 的火柴,就可以发现它无法被放在任意一组中,因此直接退出搜索返回 False。

在leetcode上面 不对数组进行排序可能会超时

代码实现

public class Solution {
    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;
        Integer[] newNums = new Integer[nums.length];
        for (int i = 0; i < nums.length; i++){
            newNums[i] = nums[i];
        }

        Arrays.sort(newNums, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2 - o1;
            }
        });
        int[] bucket = new int[4];
        return dfs(0, newNums, bucket, sum / 4);
    }

    private boolean dfs(int index, Integer[] nums, int[] bucket, int target){
        if (index >= nums.length){
            return bucket[0] == target && bucket[1] == target && bucket[2] == target && bucket[3] == target;
        }

        for (int i = 0; i<4; i++){
            if (bucket[i] + nums[index] > target){
                continue;
            }
            bucket[i] += nums[index];
            if (dfs(index + 1, nums, bucket, target)){
                return true;
            }
            bucket[i] -= nums[index];
        }
        return false;
    }

    public static void main(String[] args) {
        System.out.println(new Solution().makesquare(new int[]{1,2,3,4,9,6,5,2}));
        System.out.println(new Solution().makesquare(new int[]{1,1,2,2,2,1,1,1,1}));
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值