Leetcode 920:播放列表的数量(最详细的解法!!!)

版权声明:本文为博主原创文章,未经博主允许不得转载。有事联系:[email protected] https://blog.csdn.net/qq_17550379/article/details/82992083

你的音乐播放器里有 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]

提示:

  1. 0 <= K < N <= L <= 100

解题思路

大家首先应该可以想到的解法就是将所以的集合都找出来,然后对这些集合中相同元素的位置比较,如果位置<k,那么就剔除,最后剩下的就是我们需要的解。这种暴力解法思路很简单,但是实际操作起来并不容易,而且速度也很慢。

这个问题可以通过动态规划的方法解决。我们定义函数f(n,l,k)表示n首歌填充l个位置,相同歌的间隔超过k。那么,我们对于第l个位置来说只有两种情况

  • 之前没有相同的歌,也就是说n-1首歌填充了前面l-1个位置,即f(n-1,l-1,k)
  • 之前有相同的歌,也就是说n首歌填充了前面l-1个位置,即f(n,l-1,k)

对于第一种情况,因为有n首歌,所以会出现n次。而对于第二种情况,由于相同的歌不能间隔k,所以会出现n-k次,那么

  • f(n,l,k)=f(n-1,l-1,k)*n+f(n,l-1,k)*(n-k)

接着我们考虑边界条件:当n==l时,即为全排列,也就是n!种;当i<=K的时候,解不存在,很好理解;当n==K+1时,也是全排列,因为此时最后一首歌会和第一首歌相同。

class Solution:
    def numMusicPlaylists(self, N, L, K):
        """
        :type N: int
        :type L: int
        :type K: int
        :rtype: int
        """
        mem = [[0]*(L+1) for _ in range(N+1)]
        for i in range(K+1, N+1):
            for j in range(i, L + 1):
                if i == j or i == K + 1:
                    mem[i][j] = math.factorial(i)
                else:
                    mem[i][j] = mem[i-1][j-1]*i + mem[i][j-1]*(i - K)

        return mem[N][L]%(10**9 + 7)

reference:

https://leetcode.com/problems/number-of-music-playlists/discuss/178415/C++JavaPython-DP-Solution

我将该问题的其他语言版本添加到了我的GitHub Leetcode

如有问题,希望大家指出!!!

猜你喜欢

转载自blog.csdn.net/qq_17550379/article/details/82992083