920 Number of Music Playlists 播放列表的數量
Description:
Your music player contains n different songs. You want to listen to goal songs (not necessarily different) during your trip. To avoid boredom, you will create a playlist so that:
Every song is played at least once.
A song can only be played again only if k other songs have been played.
Given n, goal, and k, return the number of possible playlists that you can create. Since the answer can be very large, return it modulo 109 + 7.
Example:
Example 1:
Input: n = 3, goal = 3, k = 1
Output: 6
Explanation: There are 6 possible playlists: [1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], and [3, 2, 1].
Example 2:
Input: n = 2, goal = 3, k = 0
Output: 6
Explanation: There are 6 possible playlists: [1, 1, 2], [1, 2, 1], [2, 1, 1], [2, 2, 1], [2, 1, 2], and [1, 2, 2].
Example 3:
Input: n = 2, goal = 3, k = 1
Output: 2
Explanation: There are 2 possible playlists: [1, 2, 1] and [2, 1, 2].
Constraints:
0 <= k < n <= goal <= 100
題目描述:
你的音樂播放器裏有 N 首不同的歌,在旅途中,你的旅伴想要聽 L 首歌(不一定不同,即,允許歌曲重複)。請你爲她按如下規則創建一個播放列表:
每首歌至少播放一次。
一首歌只有在其他 K 首歌播放完之後才能再次播放。
返回可以滿足要求的播放列表的數量。由於答案可能非常大,請返回它模 10^9 + 7 的結果。
示例 :
示例 1:
輸入:N = 3, L = 3, K = 1
輸出:6
解釋:有 6 種可能的播放列表。[1, 2, 3],[1, 3, 2],[2, 1, 3],[2, 3, 1],[3, 1, 2],[3, 2, 1].
示例 2:
輸入:N = 2, L = 3, K = 0
輸出:6
解釋:有 6 種可能的播放列表。[1, 1, 2],[1, 2, 1],[2, 1, 1],[2, 2, 1],[2, 1, 2],[1, 2, 2]
示例 3:
輸入:N = 2, L = 3, K = 1
輸出:2
解釋:有 2 種可能的播放列表。[1, 2, 1],[2, 1, 2]
提示:
0 <= K < N <= L <= 100
思路:
動態規劃
設 dp[i][j] 表示使用 i 首歌, 其中有 j(0 < j <= min(i, n)) 首不同的歌播放順序的個數
如果聽新歌 dp[i][j] += dp[i - 1][j - 1] * (n - j + 1), 即 j - 1 首歌不同, 新歌選擇有 n - (j - 1) 種
如果聽老歌 dp[i][j] += dp[i - 1][j] * max(0, j - k), 即前面的 k 首歌需要不重複, 最少爲 0
注意到 dp[i] 只取決於 dp[i - 1] 可以用滾動數組的方式更新將空間複雜度降低爲 O(n)
時間複雜度爲 O(nL), 空間複雜度爲 O(n)
代碼:
C++:
class Solution
{
public:
int numMusicPlaylists(int n, int goal, int k)
{
vector<long> dp(n + 1, 0);
dp[1] = n;
long mod = 1e9 + 7;
for (int i = 2; i <= goal; i++) for (int j = min(i, n); j > 0; j--) dp[j] = (dp[j - 1] * (n - j + 1) + dp[j] * max(0, j - k) + mod) % mod;
return dp.back();
}
};
Java:
class Solution {
public int numMusicPlaylists(int n, int goal, int k) {
long dp[] = new long[n + 1], mod = 1_000_000_007;
dp[1] = n;
for (int i = 2; i <= goal; i++) for (int j = Math.min(i, n); j > 0; j--) dp[j] = (dp[j - 1] * (n - j + 1) + dp[j] * Math.max(j - k, 0) + mod) % mod;
return (int)dp[n];
}
}
Python:
class Solution:
def numMusicPlaylists(self, n: int, goal: int, k: int) -> int:
dp = [0] + [n] + [0] * (n - 1)
for i in range(2, goal + 1):
for j in range(min(i, n), 0, -1):
dp[j] = dp[j - 1] * (n - j + 1) + dp[j] * max(j - k, 0)
return dp[-1] % (10 ** 9 + 7)