【刷题日记】473. 火柴拼正方形

861 阅读4分钟

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

本次刷题日记的第 52 篇,力扣题为:473. 火柴拼正方形中等

一、题目描述:

火柴拼正方形,有点意思,回忆一下童年的手工课

二、这道题考察了什么思想?你的思路是什么?

题目说的比较明确,看完题目可能瞬间会有想法,可是一下子好像不知道如何去落地,来仔细看看题目要求

  • 题目给出一个数组,是每一个火柴的长度
  • 题目要求我们用给出的火柴拼出一个正方形,要求火柴不能被折断,需要我们正好能拼出一个正方形

这么一看,火柴若是摆着我们面前,能不能拼出要求的正方形,我们尝试一下就知道了,但是我们如何用程序的方式来展现呢,如何分步骤来完整这个拼接的过程 呢?

分析

拼接一个完整正方形的前提,我们要明白,火柴是不让折断的,那么我们是否应该在拼接之前,先计算一下,给出的火柴长度,加起来是否满足一个正方形的周长,我们只需要火柴全部加起来能被 4 整除即可

另外我们是不是会先找出最长的火柴来作为第一根火柴进行拼接,然后再去找合适的火柴进行适配

类似于这样打乱的火柴棍,我们用手拼接正方形的话,我们肯定是先会拿出最长的火柴来进行拼接

我们就可以先从长到短的排个队,如果不从大到小的排个队的话,我们后续进行筛选的操作,无用功太多

开始拼接正方形的时候,拿出第一根做正方形的其中一边,如果当前的这个长度,是小于需要拼接正方形的边长,那么我们就再拿次长的进行拼接,如果是已经等于需要拼接正方形的边长,那么我们再拼接第 2 条边

同理

最终,我们就可以拼接成我们期望的正方形

那么我们在编码的时候,我们如何做到先选择第一根长的,然后再去匹配后面的每一根呢?

还记得回溯法吗,上面的操作方式就可以使用回溯的方式来进行实现, 最后所有的火柴都用上了,且拼接成一个完整的正方形,那么说明给出的火柴是 ok 的

三、编码

根据上述逻辑和分析,我们就可以翻译成如下代码

注意需要将火柴按大到小的排序,否则会出现时间超限的情况,因为需要类似于如下的案例,就会时间超限,做了很多无用功

编码如下:

func makesquare(matchsticks []int) bool {
    // 校验给出的火柴总长度是否可以被 4 整除
    var total int
    for _, stick := range matchsticks {
        total += stick
    }
    if total%4 != 0 {
        return false
    }
    // 排序数组,从大到小
    sort.Sort(sort.Reverse(sort.IntSlice(matchsticks))) 
    // 开始一个一个的去拼接
    avg := total / 4
    var sqt = [4]int{}
    var dfs func(int) bool
    dfs = func(idx int) bool {
        // 已经将 matchsticks 递归完毕
        if idx == len(matchsticks) {
            return true
        }
        for i := range sqt {
            sqt[i] += matchsticks[idx]
            if sqt[i] <= avg && dfs(idx + 1) {
                return true
            }
            sqt[i] -= matchsticks[idx]
        }
        // 程序能走到这里,说明有火柴没有用上,因此直接返回 false
        return false
    }
    return dfs(0)
}

四、总结:

此处的空间复杂度相对来说比较好看出来,是 O(n) ,因此我们递归消耗了栈空间,因此是 O(n) ,那么此处的时间复杂度是多少呢,我们可以仔细来看看

按照上述的编码方式,我们可以发现,题目给出的 n 根火柴,都有机会放在 4 条边的任意一边,知道满足可以拼接成一个完整的正方形即可,因此时间复杂度是 O(4^n)

原题地址:473. 火柴拼正方形

今天就到这里,学习所得,若有偏差,还请斧正

欢迎点赞,关注,收藏

朋友们,你的支持和鼓励,是我坚持分享,提高质量的动力

好了,本次就到这里

技术是开放的,我们的心态,更应是开放的。拥抱变化,向阳而生,努力向前行。

我是小魔童哪吒,欢迎点赞关注收藏,下次见~