力扣473. 火柴拼正方形

168 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第11天,点击查看活动详情

力扣473. 火柴拼正方形

一、题目描述:

你将得到一个整数数组 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] <= 10^8

来源:力扣(LeetCode) 链接:leetcode.cn/problems/ma… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

二、思路分析:

  1. 这道题考察了什么思想?你的思路是什么?

    这道题目我们需要计算火柴的长度之和,如果该值不是4的倍数,那么不能拼成正方形,返回false。如果是4的倍数,那么我们先计算四分之一的总长度,我们按从大至小放置火柴,对于第i根火柴,我们将其放入四条边之一,目的是不能让放入该火柴后,四条边都不能超过四分之一火柴总长度,以此类推,如若所有火柴都放置后,每条边都是四分之一火柴总长度,那么就能够形成正方形。

  2. 做题的时候是不是一次通过的,遇到了什么问题,需要注意什么细节?

    不是一次通过的,判断条件时遇到了麻烦,大家一定要想清楚再做题啊。

  1. 有几种解法,哪种解法时间复杂度最低,哪种解法空间复杂度最低,最优解法是什么?其他人的题解是什么,谁的效率更好一些?用不同语言实现的话,哪个语言速度最快?

image.png

 class Solution:
     def makesquare(self, matchsticks: List[int]) -> bool:
         totalLen = sum(matchsticks)
         if totalLen % 4:
             return False
         tLen = totalLen // 4
 ​
         dp = [-1] * (1 << len(matchsticks))
         dp[0] = 0
         for s in range(1, len(dp)):
             for k, v in enumerate(matchsticks):
                 if s & (1 << k) == 0:
                     continue
                 s1 = s & ~(1 << k)
                 if dp[s1] >= 0 and dp[s1] + v <= tLen:
                     dp[s] = (dp[s1] + v) % tLen
                     break
         return dp[-1] == 0
 ​
 作者:LeetCode-Solution
 链接:https://leetcode.cn/problems/matchsticks-to-square/solution/huo-chai-pin-zheng-fang-xing-by-leetcode-szdp/
 来源:力扣(LeetCode)
 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
 class Solution {
     public boolean makesquare(int[] matchsticks) {
         int totalLen = Arrays.stream(matchsticks).sum();
         if (totalLen % 4 != 0) {
             return false;
         }
         int len = totalLen / 4, n = matchsticks.length;
         int[] dp = new int[1 << n];
         Arrays.fill(dp, -1);
         dp[0] = 0;
         for (int s = 1; s < (1 << n); s++) {
             for (int k = 0; k < n; k++) {
                 if ((s & (1 << k)) == 0) {
                     continue;
                 }
                 int s1 = s & ~(1 << k);
                 if (dp[s1] >= 0 && dp[s1] + matchsticks[k] <= len) {
                     dp[s] = (dp[s1] + matchsticks[k]) % len;
                     break;
                 }
             }
         }
         return dp[(1 << n) - 1] == 0;
     }
 }
 ​
 作者:LeetCode-Solution
 链接:https://leetcode.cn/problems/matchsticks-to-square/solution/huo-chai-pin-zheng-fang-xing-by-leetcode-szdp/
 来源:力扣(LeetCode)
 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

三、AC 代码:

 func makesquare(nums []int) bool {
     n := len(nums)
     if n < 4  || _sum(nums) % 4 != 0 {
         return false
     }
     
     sort.Slice(nums, func(i, j int) bool { 
         return nums[i] > nums[j]
     })
     state := make([]bool, n) 
     
     return dfs(0, 0, _sum(nums) / 4, 0, nums, state)
 }
 ​
 func _sum(nums []int) (res int) {
     for _, v := range nums {
         res += v
     }
     return
 }
 ​
 func dfs(k, cursum, target, start int, nums []int, state []bool) bool {
     if k == 4 {
         return true
     }
     if cursum == target {
         return dfs(k+1, 0, target, 0, nums, state)
     }
     
     for i:=start; i<len(nums); i++ {
         if state[i]==false && nums[i] + cursum <= target {
             state[i] = true
             if dfs(k, nums[i] + cursum, target, i + 1, nums, state)==true {
                 return true
             }
             state[i] = false
         }
     }
     return false
 }

四、总结:

如果你还有更多的思考、分析、总结,通通都加上来吧~

473. 火柴拼正方形

判断条件时遇到了麻烦,大家一定要想清楚再做题啊。题目有些难度!