java矩阵正方形展开_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() {

@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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值