给 N x 3 网格图涂色的方案数
难度:
标签:
题目描述
你有一个 n x 3
的网格图 grid
,你需要用 红,黄,绿 三种颜色之一给每一个格子上色,且确保相邻格子颜色不同(也就是有相同水平边或者垂直边的格子颜色不同)。
给你网格图的行数 n
。
请你返回给 grid
涂色的方案数。由于答案可能会非常大,请你返回答案对 10^9 + 7
取余的结果。
示例 1:
输入:n = 1 输出:12 解释:总共有 12 种可行的方法:![]()
示例 2:
输入:n = 2 输出:54
示例 3:
输入:n = 3 输出:246
示例 4:
输入:n = 7 输出:106494
示例 5:
输入:n = 5000 输出:30228214
提示:
n == grid.length
grid[i].length == 3
1 <= n <= 5000
代码结果
运行时间: 33 ms, 内存: 16.0 MB
/*
* 思路:
* 1. 每一行有3个格子,可以用3种颜色(红、黄、绿)进行上色,
* 相邻格子的颜色必须不同。
* 2. 第一行的12种可能性:ABA, ABC, ACB, BAC, BCA, BCB, CAB, CBA, CAC, CBC, CCB, CAC。
* 3. 每行的状态可以分为两类:
* - type1:ABA 型,有6种可能性。
* - type2:ABC 型,有6种可能性。
* 4. 通过递推关系,可以计算出第 n 行的方案数。
* 5. 用动态规划 dp1 和 dp2 表示第 n 行分别为 type1 和 type2 的方案数。
* 6. 初始值:dp1 = 6, dp2 = 6。
* 7. 状态转移方程:
* - 新的 dp1 = 2 * dp1 + 2 * dp2
* - 新的 dp2 = 2 * dp1 + 3 * dp2
* 8. 答案为 dp1 + dp2,对 10^9 + 7 取余。
*/
import java.util.stream.IntStream;
public class Solution {
public int numOfWays(int n) {
final int MOD = 1000000007;
long[] dp = {6, 6};
IntStream.range(1, n).forEach(i -> {
long newDp1 = (2 * dp[0] + 2 * dp[1]) % MOD;
long newDp2 = (2 * dp[0] + 3 * dp[1]) % MOD;
dp[0] = newDp1;
dp[1] = newDp2;
});
return (int) ((dp[0] + dp[1]) % MOD);
}
}
解释
方法:
此题解采用动态规划的方法解决问题。首先,对于一个3格宽的单行网格,有两类排列方式:不含相同色的相邻列的排列(三个颜色各不相同)和两个颜色相同、一个颜色不同的排列。对于第一种情况,有6种排列(如红黄绿、红绿黄等),对于第二种情况,也有6种(如红红黄、黄红红等)。当增加更多行时,下一行的颜色排列方式会依赖于上一行的颜色排列。具体地说,对于第一种类型的排列,下一行可以是第一种类型的3种排列或第二种类型的2种排列。对于第二种类型的排列,下一行可以是第一种类型的2种排列或第二种类型的2种排列。使用两个变量`a`和`b`分别跟踪第一种和第二种类型的排列数量,并迭代更新这些值直到达到所需的行数。最后,返回`a`和`b`的总和,即总的排列数量。
时间复杂度:
O(n)
空间复杂度:
O(1)
代码细节讲解
🦆
为什么初始化a和b的值都是6,这两个值分别代表了什么意义?
▷🦆
在进行动态规划更新时,a和b的更新公式`(3*a + 2*b) % 1000000007`和`(2*a + 2*b) % 1000000007`是如何得出的?请解释这些系数的来源。
▷🦆
题解中提到了两种类型的排列,能否具体解释这两种排列各自的特点以及它们如何影响行与行之间的颜色分配?
▷🦆
为什么在最后返回时需要再次进行模运算`(a + b) % 1000000007`?
▷