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