题目地址:
https://www.lintcode.com/problem/paint-fence/description
给定 n n n个柱子,可以染 k k k种颜色,要求不能有连续超过两个相邻的柱子颜色一样,问有多少种染色方法。
思路是动态规划。设 f [ i ] f[i] f[i]是有 i i i根柱子的情况下有多少种染色方法。那么如果第 i − 1 i-1 i−1根与第 i i i根柱子颜色相同,则有 ( k − 1 ) f [ i − 2 ] (k-1)f[i-2] (k−1)f[i−2]种方法(这是根据对称性,第 i − 2 i-2 i−2根柱子只能涂 k − 1 k-1 k−1种颜色,每种颜色有 f [ i − 1 ] / k f[i-1]/k f[i−1]/k种方法,所以在第 i − 1 i-1 i−1根柱子颜色确定的情况下,前 i − 2 i-2 i−2根柱子有 f [ i − 1 ] / k × ( k − 1 ) f[i-1]/k\times(k-1) f[i−1]/k×(k−1)种方法,但第 i − 1 i-1 i−1根柱子有 k k k种方案,所以一共 f [ i − 1 ] / k × ( k − 1 ) × k = ( k − 1 ) f [ i − 2 ] f[i-1]/k\times(k-1)\times k=(k-1)f[i-2] f[i−1]/k×(k−1)×k=(k−1)f[i−2]种方案);如果第 i − 1 i-1 i−1根与第 i i i根柱子颜色不同,则有 ( k − 1 ) f [ i − 1 ] (k-1)f[i-1] (k−1)f[i−1]种方案,论证类似。所以有 f [ i ] = ( k − 1 ) ( f [ i − 1 ] + f [ i − 2 ] ) f[i]=(k-1)(f[i-1]+f[i-2]) f[i]=(k−1)(f[i−1]+f[i−2])初始条件 f [ 1 ] = k , f [ 2 ] = k 2 f[1]=k,f[2]=k^2 f[1]=k,f[2]=k2,对于 f [ 0 ] f[0] f[0]则缺乏定义,可以定义为 1 1 1或者 0 0 0,我们要从 f [ 3 ] f[3] f[3]开始递推。代码如下:
public class Solution {
/**
* @param n: non-negative integer, n posts
* @param k: non-negative integer, k colors
* @return: an integer, the total number of ways
*/
public int numWays(int n, int k) {
// write your code here
int[] dp = new int[Math.max(3, n + 1)];
dp[0] = 1;
dp[1] = k;
dp[2] = k * k;
// 从3开始递推
for (int i = 3; i <= n; i++) {
dp[i] = (k - 1) * (dp[i - 1] + dp[i - 2]);
}
return dp[n];
}
}
时空复杂度 O ( n ) O(n) O(n)。