0276. 栅栏涂色
大约 3 分钟
--- 
0276. 栅栏涂色
- 标签:动态规划
- 难度:中等
题目链接
题目大意
描述:
有 种颜色的涂料和一个包含 个栅栏柱的栅栏,请你按下述规则为栅栏设计涂色方案:
- 每个栅栏柱可以用其中「一种」颜色进行上色。
- 相邻的栅栏柱「最多连续两个」颜色相同。
给定两个整数 和 。
要求:
返回所有有效的涂色「方案数」。
说明:
- 。
- 。
- 题目数据保证:对于输入的 和 ,其答案在范围 内。
示例:
- 示例 1:

输入:n = 3, k = 2
输出:6
解释:所有的可能涂色方案如上图所示。注意,全涂红或者全涂绿的方案属于无效方案,因为相邻的栅栏柱 最多连续两个 颜色相同。
- 示例 2:
输入:n = 1, k = 1
输出:1
解题思路
思路 1:动态规划
这是一个经典的动态规划问题。我们需要计算在相邻栅栏柱最多连续两个颜色相同的约束下,有多少种涂色方案。
核心思想是:
- 定义状态: 表示前 个栅栏柱的涂色方案数。
- 状态转移:考虑第 个栅栏柱的涂色情况:
- 如果第 个栅栏柱与第 个栅栏柱颜色不同,有 种方案。
- 如果第 个栅栏柱与第 个栅栏柱颜色相同,但第 个与第 个颜色不同,有 种方案。
- 状态转移方程:
具体算法步骤:
- 处理边界情况:如果 ,返回 ;如果 ,返回 ;如果 ,返回 。
- 初始化状态:,,。
- 状态转移:对于 从 到 ,计算 。
- 返回 。
思路 1:代码
class Solution:
def numWays(self, n: int, k: int) -> int:
# 处理边界情况
if n == 0:
return 0
if n == 1:
return k
if n == 2:
return k * k
# 初始化 dp 数组
# dp[i] 表示前 i 个栅栏柱的涂色方案数
dp = [0] * (n + 1)
dp[0] = 0
dp[1] = k
dp[2] = k * k
# 状态转移
for i in range(3, n + 1):
# 第 i 个栅栏柱的涂色方案数 = (前 i-1 个的方案数 + 前 i-2 个的方案数) × (k-1)
# 其中 k-1 表示与前面栅栏柱颜色不同的选择数
dp[i] = (dp[i-1] + dp[i-2]) * (k - 1)
return dp[n]
思路 1:复杂度分析
- 时间复杂度:,其中 是栅栏柱数量。需要遍历 个状态进行状态转移。
- 空间复杂度:,需要 的空间存储 数组。