小R的随机播放问题 | 青训营X豆包MarsCode 技术训练营

33 阅读3分钟

小R的随机播放问题解析

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

问题描述

给定一个长度为 ( n ) 的数组 ( a ),表示歌单中的歌曲 ID。你的任务是模拟小R的随机播放规则,输出歌曲的实际播放顺序。

输入说明

  • 整数 ( n ) (1 ≤ n ≤ 1000):歌单中歌曲的数量。
  • 数组 ( a ) (长度为 ( n )):包含 ( n ) 个不同的整数,表示歌曲的 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. 初始化队列:将歌曲 ID 加入一个队列中,便于实现 FIFO(先进先出)操作。

  2. 循环播放

    • 每次从队列中取出第一个元素(播放当前歌曲),并将其添加到结果列表中。
    • 如果队列中还有歌曲,则将当前第一个元素移到队列的末尾。
  3. 直到队列为空:重复上述操作,直到队列中没有歌曲为止。

代码实现

以下是实现该算法的 Python 代码:

from collections import deque

def random_play_order(n: int, a: list) -> list:
    queue = deque(a)  # 使用双端队列
    result = []       # 存储播放顺序

    while queue:
        # 播放当前第一首歌
        current_song = queue.popleft()
        result.append(current_song)

        # 如果队列不为空,将当前歌曲移到队尾
        if queue:
            next_song = queue.popleft()  # 取出队列的下一个元素
            queue.append(next_song)       # 将其移到队尾

    return result

代码解析

  1. 导入库:

    • from collections import deque: 导入双端队列 deque,它支持在队列的两端进行高效的插入和删除操作。
  2. 函数定义:

    • random_play_order(n: int, a: list) -> list: 接收两个参数,n 为歌曲数量,a 为歌曲的 ID 列表,返回歌曲的实际播放顺序。
  3. 使用双端队列:

    • 初始化队列 queue = deque(a),将所有歌曲 ID 添加到队列中。
    • 创建一个空列表 result 用于存储播放顺序。
  4. 循环播放:

    • 使用 while queue: 循环,直到队列为空。
    • current_song = queue.popleft() 从队列中取出并播放第一首歌。
    • 将播放的歌曲添加到结果列表 result.append(current_song)
    • 如果队列不为空,取出下一个歌曲 next_song = queue.popleft() 并将其添加到队列的末尾 queue.append(next_song)
  5. 返回结果:

    • 最后返回 result,即实际的播放顺序。

时间复杂度分析

  • 时间复杂度: O(n),因为每首歌都会被处理一次,队列的操作(添加和删除)都是 O(1) 的时间复杂度。
  • 空间复杂度: O(n),用于存储队列和结果列表。