【2022-11-12每日一题】790. 多米诺和托米诺平铺[Medium]

2022-11-12
2分钟阅读时长

2022-11-12每日一题:790. 多米诺和托米诺平铺

难度:Medium

标签:动态规划

有两种形状的瓷砖:一种是 2 x 1 的多米诺形,另一种是形如 "L" 的托米诺形。两种形状都可以旋转。

给定整数 n ,返回可以平铺 2 x n 的面板的方法的数量。返回对 109 + 7 取模 的值。

平铺指的是每个正方形都必须有瓷砖覆盖。两个平铺不同,当且仅当面板上有四个方向上的相邻单元中的两个,使得恰好有一个平铺有一个瓷砖占据两个正方形。

 

示例 1:

输入: n = 3
输出: 5
解释: 五种不同的方法如上所示。

示例 2:

输入: n = 1
输出: 1

 

提示:

  • 1 <= n <= 1000

方法一:动态规划

详细思路过程见官方题解,这里只做个人刷题记录,方便后续查询阅读

解释

image-20221113204737324

代码

func numTilings(n int) int {
    const mod int = 1e9+7
    dp := make([][4]int, n+1)
    dp[0][3] = 1
    for i := 1; i <= n; i++ {
        dp[i][0] = dp[i-1][3] // 一个正方形都没有被覆盖,记为状态 0
        dp[i][1] = (dp[i-1][0] + dp[i-1][2])%mod// 只有上方的正方形被覆盖,记为状态 1
        dp[i][2] = (dp[i-1][0] + dp[i-1][1])%mod// 只有下方的正方形被覆盖,记为状态 2
        // 上下两个正方形都被覆盖,记为状态 3
        dp[i][3] = (((dp[i-1][0] + dp[i-1][1])%mod + dp[i-1][2])%mod + dp[i-1][3])%mod
    }
	return dp[n][3]
}

复杂度分析

  • 时间复杂度:O(n),其中 n 是总列数。

  • 空间复杂度:O(n)。保存 dp 数组需要 O(n) 的空间。

方法二:矩阵快速幂

详细思路过程见官方题解,这里只做个人刷题记录,方便后续查询阅读

image-20221113210855864

代码

const mod int = 1e9 + 7

type matrix [4][4]int

func (a matrix) mul(b matrix) matrix {
    c := matrix{}
    for i, row := range a {
        for j := range b[0] {
            for k, v := range row {
                c[i][j] = (c[i][j] + v*b[k][j]) % mod
            }
        }
    }
    return c
}

func (a matrix) pow(n int) matrix {
    res := matrix{}
    for i := range res {
        res[i][i] = 1
    }
    for ; n > 0; n >>= 1 {
        if n&1 > 0 {
            res = res.mul(a)
        }
        a = a.mul(a)
    }
    return res
}

func numTilings(n int) int {
    m := matrix{
        {0, 0, 0, 1},
        {1, 0, 1, 0},
        {1, 1, 0, 0},
        {1, 1, 1, 1},
    }
    return m.pow(n)[3][3]
}

复杂度分析

  • 时间复杂度:O(logn),其中 n 是总列数。矩阵快速幂的时间复杂度为 O(log⁡n)。

  • 空间复杂度:O(1)。

LeetCode题库地址

此题还需继续理解,暂未掌握