leetcode 473. 火柴拼正方形 通过快速判断击败100%

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

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

示例 1:

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

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

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

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

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


```java
 public boolean makesquare(int[] nums) {
         if (nums.length < 4) {
            return false;
        }

        int sum = 0;
        for (int i = nums.length - 1; i >= 0; i--) {
            sum += nums[i];
        }
        //快速判断总和是否是4的倍数
        if (sum % 4 != 0) {
            return false;
        }
        Arrays.sort(nums);
        int target = sum / 4;
        //快速判断最大的数是否超过了四分之一
        if (nums[nums.length - 1] > target) {
            return false;
        }
        boolean[] visit = new boolean[nums.length];
        //循环4次,从大到小每次找到一条符合条件的边
        for (int i = 3; i >= 0; i--) {
            if (!ok(target, nums, visit, nums.length - 1)) {
                return false;
            }
        }
        return true;
    }

    static boolean ok(int target, int[] nums, boolean[] visit, int startPos) {
    //从大到小遍历,通过startPos计算当前遍历到的偏移量
        for (int i = startPos; i >= 0; i--) {
        //已经使用过的用visit标记,跳过
        //nums[i]有可能大于当前剩余目标值,也要跳过
            if (visit[i] || nums[i] > target) {
                continue;
            } else if (nums[i] == target) {
            //找到目标值可以直接标记返回
                visit[i] = true;
                return true;
            } else {
            //找到当前小于目标值的最大值,标记后再往前寻找剩余目标值
                visit[i] = true;
                if (ok(target - nums[i], nums, visit, i - 1)) {
                    return true;
                }
                //到这里说明这次递归没有找到目标值,那么要将这次的标记还原
                visit[i] = false;
            }
        }
        //遍历完都没找到目标值,说明没有符合条件的情况
        return false;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值