920. Number of Music Playlists

排列组合 + DP
这道题即考了排列组合的知识又考了DP的知识。
这道题的难点在于两处。
1。 DP的定义
2。DP 的递归关系。
好像这话说了等于没说,DP的难点不都是这样的吗 :)
DP 定义永远是个难点。经常我们会想用前n个组成 l首歌的playlist。
当我们用n + 1首歌时的递推关系
dp[n + 1][l] = n * dp[n][l] +???(完全用n + 1首歌组成的playlist)
这里我就完全推不下去了。

看了一下答案他用了另外一种定义,这里dp[n][l]的意思是
用n首distinct的歌组成长度为l的playlist的数量。
注意这是n首, 不是前n首,任意n首都可以
而且这n首一定要完完全全的用上。

dp[n][l] = dp[n - 1][l - 1] * (N - (n - 1)) 用一首之前没用过的歌组成playlist的最后一首
+ dp[n][l -1] * (n - K) 用一首之用过歌组成playlist的最后一首,但要排除最后 K个。
n- K如果小于 0就取 0.

有了这个定义。一切就好办了。

class Solution {
    public int numMusicPlaylists(int N, int L, int K) {
        int MOD = 1_000_000_007;
        long[][] dp = new long[N + 1][L + 1];
        for (int n = 0; n <= N; n++) {
            for (int l = 0; l <= L; l++) {
                if (n + l == 0) {
                    dp[n][l] = 1; // good.
                } else if (n == 0 && l != 0) {
                    dp[n][l] = 0; // no playlist.
                } else if (n != 0 && l == 0) {
                    dp[n][l] = 0; // all the songs must be placed once
                } else {
                    dp[n][l] += dp[n - 1][l - 1] * (N - (n - 1));
                    dp[n][l] %= MOD;
                    dp[n][l] += dp[n][l - 1] * (n - K < 0 ? 0 : n - K);
                    dp[n][l] %= MOD;
                }
            }
        }
        return (int) dp[N][L];
    }
}

你可能感兴趣的:(920. Number of Music Playlists)