276. Paint Fence

458 查看

题目:
There is a fence with n posts, each post can be painted with one of the k colors.

You have to paint all the posts such that no more than two adjacent fence posts have the same color.

Return the total number of ways you can paint the fence.

Note:
n and k are non-negative integers.

解答:
这道题其实跟house rob很类似,用dp做的时候在function部分很容易写错,当取跟前面不一样的颜色时,这一轮一共有除了前面这个颜色的k-1个颜色可以选;当取跟前面一样的颜色的时候,这一轮只有一种情况可以选,且:前一轮不能取跟前前一轮一样的颜色,否则这三个post的颜色就都相同了,不符合题中说的最多两个相邻的post颜色相同。代码如下:

public class Solution {
    //State: f[i][j] is total number of ways we can paint the fence;
    //Function: f[i][0] = f[i - 1][0] * k - 1 + f[i - 1][1] * (k - 1)
    //          f[i][1] = f[i - 1][0] + f[i - 1][1]
    //Initialize: f[0][0] = k, f[0][1] = k; f[1][0] = k * (k - 1), f[1][1] = k;
    //Result: f[n - 1][0] + f[n - 1][1];
    public int numWays(int n, int k) {
        if (n == 0 || k == 0) return 0;
        if (n == 1) return k;
        int[][] f = new int[n][2];
        //Initialize
        f[0][1] = f[1][1] = k;
        f[0][0] = k;
        f[1][0] = k * (k - 1);
        //f[i][0]表示跟前面不一样颜色,f[i][1]表示跟前面一样颜色
        for (int i = 2; i < n; i++) {
            //跟前面不一样颜色的话,在这轮有k - 1种可能性
            f[i][0] = f[i - 1][0] * (k - 1) + f[i - 1][1] * (k - 1);
            //跟前面一样颜色的话,在这轮有1种可能性,且前一轮不能与前前一轮一样颜色
            f[i][1] = f[i - 1][0];
        }
        
        return f[n - 1][0] + f[n - 1][1];
    }
}

因为这个dp的解法里,我们只用到变量i - 1和i,所以我们可以进定步把空间复杂度降为o(1):

 //Save space to O(1) because it only cares about i - 1 and i
    public int numWays(int n, int k) {
        if (n == 0 || k == 0) return 0;
        if (n == 1) return k;
        int diff = k * (k - 1);
        int same = k;
        for (int i = 2; i < n; i++) {
            int tmp = diff;
            diff = (diff + same) * (k - 1);
            same = tmp;
        }
        return same + diff;
    }