276. Paint Fence

求总数而不用给出方案,很可能是动态规划问题。有两种思路都可以做,本质是一样的:都是对当前颜色与前一个颜色是否相同进行分类。

思路一:

dp[i] 表示到下标i为止的方案数。dp[n-1] 为所求。

dp[i] 由两种情况构成:

如果 i-1 颜色与 i 颜色相同,则 dp[i] = dp[i-2] * (k-1)   乘以k-1的原因是,i-1 和 i 有k-1种可能性。

如果 i-1 颜色与 i 颜色不同,则 dp[i] = dp[i-1] * (k-1)   同理,i 有k-1种可能性。

所以递推公式为 dp[i] = dp[i-2] * (k-1) + dp[i] = dp[i-1] * (k-1)     i>=2

base cases 单独计算一下,dp[0]=k,dp[1]=k+k*(k-1)  相同颜色k种,不同颜色k(k-1)种。

class Solution {
public:
    int numWays(int n, int k) {
        if (n==0 || k==0) return 0;
        if (n==1) return k;
        int dp[n];
        dp[0]=k;
        dp[1]=k+k*(k-1);
        for (int i=2;i<n;++i){
            dp[i] = dp[i-2]*(k-1) + dp[i-1]*(k-1);
        }
        return dp[n-1];
    }
};

思路二:

dp[i] = same[i] + diff[i],dp[i] 和上面定义一样,same[i] 表示 i 与 i-1 颜色相同的情况下的方案数,而 diff[i] 表示 i 与 i-1 颜色不同的情况下的方案数。dp[n-1] = same[n-1] + diff[n-1] 为所求。

对于 same[i],i 与 i-1 颜色相同,i-1 与 i-2 颜色一定不同,因此 same[i] = diff[i-1] * (k-1)

对于 diff[i],i-1 可能与 i-2 x相同,也可能不同,所以 diff[i] = same[i-1] * (k-1) + diff[i-1] * (k-1) 

i = 0 时,same[0] 和 diff[0] 没有意义,

same[1] = k,  diff[1] = k*k(-1)

class Solution {
public:
    int numWays(int n, int k) {
        if (n==0 || k==0) return 0;
        if (n==1) return k;
        
        int same[n];
        int diff[n];
        same[1]=k;
        diff[1]=k*(k-1);
        for (int i=2;i<n;++i){
            same[i] = diff[i-1];
            diff[i] = same[i-1]*(k-1) + diff[i-1]*(k-1);
        }
        return same[n-1]+diff[n-1];
    }
};

上述两种方法都可以用三个变量将空间复杂度减少到O(1)

猜你喜欢

转载自www.cnblogs.com/hankunyan/p/9157604.html