Skip to content

Commit 2447afc

Browse files
author
lucifer
committed
feat: $790
1 parent 2cddbca commit 2447afc

File tree

3 files changed

+160
-0
lines changed

3 files changed

+160
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ leetcode 题解,记录自己的 leetcode 解题之路。
323323
- [0718. 最长重复子数组](./problems/718.maximum-length-of-repeated-subarray.md)
324324
- [0754. 到达终点数字](./problems/754.reach-a-number.md)
325325
- [0785. 判断二分图](./problems/785.is-graph-bipartite.md)
326+
- [0790. 多米诺和托米诺平铺](./problems/790.domino-and-tromino-tiling.md) 🆕
326327
- [0799. 香槟塔](./problems/799.champagne-tower.md) 🆕
327328
- [0801. 使序列递增的最小交换次数](./problems/801.minimum-swaps-to-make-sequences-increasing.md) 🆕
328329
- [0816. 模糊坐标](./problems/816.ambiguous-coordinates.md)

SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@
187187
- [0718. 最长重复子数组](./problems/718.maximum-length-of-repeated-subarray.md)
188188
- [0754. 到达终点数字](./problems/754.reach-a-number.md)
189189
- [0785. 判断二分图](./problems/785.is-graph-bipartite.md)
190+
- [0790. 多米诺和托米诺平铺](./problems/790.domino-and-tromino-tiling.md) 🆕
190191
- [0799. 香槟塔](./problems/799.champagne-tower.md) 🆕
191192
- [0801. 使序列递增的最小交换次数](./problems/801.minimum-swaps-to-make-sequences-increasing.md) 🆕
192193
- [0816. 模糊坐标](./problems/816.ambiguous-coordinates.md)
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
## 题目地址(790. 多米诺和托米诺平铺)
2+
3+
https://leetcode-cn.com/problems/domino-and-tromino-tiling/
4+
5+
## 题目描述
6+
7+
```
8+
有两种形状的瓷砖:一种是 2x1 的多米诺形,另一种是形如 "L" 的托米诺形。两种形状都可以旋转。
9+
10+
XX <- 多米诺
11+
12+
XX <- "L" 托米诺
13+
X
14+
15+
16+
给定 N 的值,有多少种方法可以平铺 2 x N 的面板?返回值 mod 10^9 + 7。
17+
18+
(平铺指的是每个正方形都必须有瓷砖覆盖。两个平铺不同,当且仅当面板上有四个方向上的相邻单元中的两个,使得恰好有一个平铺有一个瓷砖占据两个正方形。)
19+
20+
示例:
21+
输入: 3
22+
输出: 5
23+
解释:
24+
下面列出了五种不同的方法,不同字母代表不同瓷砖:
25+
XYZ XXZ XYY XXY XYY
26+
XYZ YYZ XZZ XYY XXY
27+
28+
提示:
29+
30+
N  的范围是 [1, 1000]
31+
32+
 
33+
```
34+
35+
## 前置知识
36+
37+
- 动态规划
38+
39+
## 公司
40+
41+
- 暂无
42+
43+
## 思路
44+
45+
这种题目和铺瓷砖一样,这种题目基本都是动态规划可解。做这种题目的诀窍就是将所有的可能都列举出来,然后分析问题的最优子结构。最后根据子问题之间的递推关系解决问题。
46+
47+
如果题目只有 XX 型,或者只有 L 型,实际上就很简单了。而这道题是 XX 和 L,则稍微有点难度。力扣还有一些其他更复杂度的铺瓷砖,都是给你若干瓷砖,让你刚好铺满一个形状。大家做完这道题之后可以去尝试一下其他题相关目。
48+
49+
以这道题来说,所有可能的情况无非就是以下 6 种:
50+
51+
![](https://tva1.sinaimg.cn/large/008eGmZEly1gnqf5s4jhaj30h80qijsk.jpg)
52+
53+
![](https://tva1.sinaimg.cn/large/008eGmZEly1gnqf6033vrj30du0qswfn.jpg)
54+
55+
而题目要求的是**刚好铺满** 2 \* N 的情况的总的可能数。
56+
57+
如上图 1,2,3,5 可能是刚好铺满 2 _ N 的瓷砖的**最后一块砖**,换句话说 4 和 6 不能是刚好铺满 2 _ N 的最后一块瓷砖。
58+
59+
为了方便描述,我们令 F(n) 表示刚好铺满 2 \* n 的瓷砖的总的可能数,因此题目要求的其实就是 F(n)。
60+
61+
- 如果最后一块选择了形状 1,那么**此时**的刚好铺满 2 \* n 的瓷砖的总的可能数是 F(n-2)
62+
- 如果最后一块选择了形状 2,那么**此时**的刚好铺满 2 \* n 的瓷砖的总的可能数是 F(n-1)
63+
- 如果最后一块选择了形状 3,那么**此时**的刚好铺满 2 \* n 的瓷砖的总的可能数是 ?
64+
- 如果最后一块选择了形状 5,那么**此时**的刚好铺满 2 \* n 的瓷砖的总的可能数是 ?
65+
- 如果最后一块选择了形状 4 和 6,那么**此时**的刚好铺满 2 \* n 的瓷砖的总的可能数是 0。换句话说 4 和 6 不可能是刚好铺满的最后一块砖。
66+
67+
虽然 4 和 6 不可能是刚好铺满的最后一块砖,但其实可以是中间状态,中间状态可以进一步转移到**刚好铺满的状态**。比如股票问题就是这样,虽然我们的最终答案不可能是买入之后,一定是卖出,但是中间的过程可以卖出,通过卖出转移到最终状态。
68+
69+
现在的问题是如何计算:最后一块选择了形状 3 和 最后一块选择了形状 5 的总的可能数,以及 4 和 6 在什么情况下选择。实际上,我们只需要考虑选择我 3 和 5 的总的可能数就行了,其原因稍后你就知道了。
70+
71+
为了表示所有的情况,我们需要另外一个状态定义和转移。 我们令 T(n) 表示刚好铺满 2 \* (N - 1)瓷砖,最后一列只有一块瓷砖的总的可能数。对应上图中的 4 和 6。
72+
73+
经过这样的定义,那么就有:
74+
75+
- 如果最后一块选择了形状 3,那么刚好铺满 2 \* (N - 1)瓷砖,最后一列只有一块瓷砖的总的可能数是 T(n -1)
76+
- 如果最后一块选择了形状 5,那么刚好铺满 2 \* (N - 1)瓷砖,最后一列只有一块瓷砖的总的可能数是 T(n-1)
77+
78+
> 大家可以根据基本图形画一下试试就知道了。同时你也应该理解了 4 和 6 在什么情况下使用。
79+
80+
根据以上的信息有如下公式:
81+
82+
```
83+
F(n) = F(n-1) + F(n-2) + 2 * T(n-1)
84+
```
85+
86+
由于上述等式有两个变量,因此至少需要两个这样的等式才可解。而上面的等式是 F(n) = xxx,因此一个直觉找到一个类似 T(n) = xxx 的公式。不难发现如下等式:
87+
88+
```
89+
T(n) = F(n-2) + T(n-1)
90+
```
91+
92+
将上面两个公式进行合并。具体来说就是:
93+
94+
```
95+
F(n) = F(n-1) + F(n-2) + 2 * T(n-1)
96+
T(n) = F(n-2) + T(n-1) -> T(n-1) = F(n-3) + T(n-2) -> 2 * T(n-1) = 2 * F(n-3) + 2 * T(n-2)
97+
```
98+
99+
进一步:
100+
101+
```
102+
F(n) = F(n-1) + 2 * F(n-3) + F(n-2) + 2T(n-2) = F(n-1) + F(n-3) + F(n-3) + F(n-2) + 2T(n-2) = F(n-1) + F(n-3) + F(n-1) = 2 * F(n-1) + F(n-3)
103+
```
104+
105+
至此,我们得出了状态转移方程:
106+
107+
```
108+
F(n) = 2 * F(n-1) + F(n-3)
109+
```
110+
111+
## 关键点
112+
113+
- 识别最优子结构
114+
- 对一块瓷砖能拼成的图形进行分解,并对每一种情况进行讨论
115+
116+
## 代码
117+
118+
- 语言支持:Python3
119+
120+
Python3 Code:
121+
122+
```python
123+
124+
class Solution:
125+
def numTilings(self, N: int) -> int:
126+
dp = [0] * (N + 3)
127+
# f(3) = 2 * f(2) + f(0) = 2 + f(0) = 1 -> f(0) = -1
128+
# f(4) = 2 * f(3) + f(1) = 2 + f(1) = 2 -> f(1) = 0
129+
dp[0] = -1
130+
dp[1] = 0
131+
dp[2] = 1
132+
# f(n) = f(n-1) + f(n-2) + 2 * T(n-1)
133+
# 2 * T(n-1) = 2 * f(n-3) + 2 * T(n-2)
134+
# f(n) = f(n-1) + 2 * f(n-3) + f(n-2) + 2T(n-2) = f(n-1) + f(n-3) + f(n-3) + f(n-2) + 2T(n-2) = f(n-1) + f(n-3) + f(n-1) = 2 * f(n-1) + f(n-3)
135+
for i in range(3, N + 3):
136+
dp[i] = 2 * dp[i-1] + dp[i-3]
137+
return dp[-1] % (10 ** 9 + 7)
138+
139+
```
140+
141+
**复杂度分析**
142+
143+
令 n 为数组长度。
144+
145+
- 时间复杂度:$O(n)$
146+
- 空间复杂度:$O(n)$
147+
148+
使用滚动数组优化可以将空间复杂度降低到 $O(1)$,大家可以试试。
149+
150+
> 此题解由 [力扣刷题插件](https://leetcode-pp.github.io/leetcode-cheat/?tab=solution-template) 自动生成。
151+
152+
力扣的小伙伴可以[关注我](https://leetcode-cn.com/u/fe-lucifer/),这样就会第一时间收到我的动态啦~
153+
154+
以上就是本文的全部内容了。大家对此有何看法,欢迎给我留言,我有时间都会一一查看回答。更多算法套路可以访问我的 LeetCode 题解仓库:https://github.com/azl397985856/leetcode 。 目前已经 40K star 啦。大家也可以关注我的公众号《力扣加加》带你啃下算法这块硬骨头。
155+
156+
关注公众号力扣加加,努力用清晰直白的语言还原解题思路,并且有大量图解,手把手教你识别套路,高效刷题。
157+
158+
![](https://tva1.sinaimg.cn/large/007S8ZIlly1gfcuzagjalj30p00dwabs.jpg)

0 commit comments

Comments
 (0)