24. 小R的随机播放顺序 | 豆包MarsCode AI刷题

72 阅读3分钟

中等题: 小R的随机播放顺序

问题描述

小R有一个特殊的随机播放规则。他首先播放歌单中的第一首歌,播放后将其从歌单中移除。如果歌单中还有歌曲,则会将当前第一首歌移到最后一首。这个过程会一直重复,直到歌单中没有任何歌曲。

例如,给定歌单 [5, 3, 2, 1, 4],真实的播放顺序是 [5, 2, 4, 1, 3]

保证歌曲中的id两两不同。

测试样例

样例1:

输入:n = 5 ,a = [5, 3, 2, 1, 4]
输出:[5, 2, 4, 1, 3]

样例2:

输入:n = 4 ,a = [4, 1, 3, 2]
输出:[4, 3, 1, 2]

样例3:

输入:n = 6 ,a = [1, 2, 3, 4, 5, 6]
输出:[1, 3, 5, 2, 6, 4]

解题思路

普通解法

我们可以通过在原数组上操作并标记已播放的歌曲,实现模拟随机播放过程。

解题思路

  1. 初始化变量

• 使用变量 play_order 保存实际的播放顺序。

• 使用 index 记录当前播放的位置。

  1. 播放当前歌曲

• 每次播放数组中 index 位置的歌曲,将其加入 play_order。

• 标记该歌曲为已播放(将其设置为 None)。

  1. 找到下一首未播放的歌曲

• 如果当前播放的歌曲不是最后一首,则从当前位置 index 开始循环,跳过所有标记为 None 的元素,找到下一首未播放的歌曲。

• 如果没有未播放的歌曲,则停止循环。

  1. 重复步骤,直到所有歌曲都被播放。

代码实现

def solution(n: int, a: list) -> list:
    play_order = []  # 记录实际播放顺序
    index = 0  # 当前播放的位置
    while len(play_order) < n:  # 当未播放的歌曲还存在时
        # 播放当前歌曲
        play_order.append(a[index])
        # 标记当前歌曲为已播放
        a[index] = None
        # 找到下一首未播放的歌曲
        if len(play_order) < n:
            # 跳过已播放的歌曲
            while a[index] is None:
                index = (index + 1) % n
            # 移动到下一首未播放的歌曲
            index = (index + 1) % n
            while a[index] is None:
                index = (index + 1) % n
    return play_order

复杂度分析

  1. 时间复杂度

• 每次找到下一首未播放的歌曲时,可能需要跳过 n 首歌曲,因此最坏情况下的时间复杂度为 O(n²)

  1. 空间复杂度

• 由于直接在输入数组 a 上标记已播放的歌曲,未引入额外的数据结构,因此空间复杂度为 O(1)

优化解法

从第一首歌开始播放,播放后就将其移除,然后将之后的第一首歌移到最后。我们很自然的可以想到使用双端队列来进行操作。方便从前面出队 也方便将元素移到末尾

解题思路

  1. 首先将歌单中的歌曲加载到双端队列中。

  2. 每次从队列中移除第一个元素(首歌)并将其添加到播放顺序列表中。

  3. 如果队列中还有剩余歌曲,则将当前的第一个元素移到队列末尾。

  4. 重复上述步骤,直到队列为空。

代码实现

from collections import deque

def solution(n: int, a: list) -> list:
    # 使用 deque 作为队列
    queue = deque(a)
    play_order = []

    while queue:
        # 播放当前第一首歌
        play_order.append(queue.popleft())
        
        # 如果队列中还有歌曲,将当前第一首歌移到最后
        if queue:
            queue.append(queue.popleft())

    return play_order

复杂度分析

  • 时间复杂度:每次操作只涉及移除队首和添加到队尾,单次操作为 O(1)。对于 n 首歌,总共有 O(n) 次操作。
  • 空间复杂度:使用了一个双端队列来存储歌单,空间复杂度为 O(n)。