小R的随机播放规则题目解析 | 豆包MarsCode AI刷题

122 阅读4分钟

题目解析:小R的随机播放规则

在这个问题中,我们需要模拟一个特殊的歌曲播放顺序。小R的随机播放规则是:首先播放歌单中的第一首歌,播放后将其从歌单中移除。接下来,他会将当前歌单中的第一首歌移到歌单的最后一位,然后继续播放新的第一首歌,直到歌单为空。

给定一个歌单,任务是模拟这个播放过程,返回实际的播放顺序。

题目分析

  1. 输入说明

    • 输入一个整数 n,表示歌单中歌曲的数量。
    • 输入一个整数列表 a,表示歌单中的歌曲,a[i] 表示第 i 首歌的 ID。
  2. 输出说明

    • 输出一个列表,表示实际播放的歌曲顺序。

解决思路

我们可以通过以下步骤来实现这个模拟过程:

  • 将给定的歌单 a 转换为一个队列(queue)。队列是一个适合模拟这种“先进先出”(FIFO)操作的数据结构。我们每次从队列的前端取出一首歌播放,然后将剩下的歌曲重新调整,按规则将当前第一首歌移动到队列的末尾。

  • 使用队列的基本操作:

    • popleft() :从队列的左端(即当前第一首歌)移除并返回该元素。
    • append() :将当前第一首歌添加到队列的末尾。

具体步骤

  1. 将输入列表 a 转换为一个队列 queue

  2. 创建一个空列表 result 用来存储实际的播放顺序。

  3. 遍历队列,直到队列为空:

    • 每次从队列中取出第一首歌并添加到 result
    • 如果队列非空,将当前的第一首歌移到队列的末尾。
  4. 最终返回 result

代码实现

from collections import deque

def solution(n: int, a: list) -> list:
    # 将歌单转换为队列
    queue = deque(a)
    result = []
    
    # 模拟播放过程
    while queue:
        # 播放当前队列中的第一首歌
        first_song = queue.popleft()
        result.append(first_song)
        
        # 如果队列非空,将当前的第一首歌移动到队列末尾
        if queue:
            next_song = queue.popleft()
            queue.append(next_song)
    
    return result

# 测试样例
if __name__ == '__main__':
    print(solution(n = 5, a = [5, 3, 2, 1, 4]))  # 输出: [5, 2, 4, 1, 3]
    print(solution(n = 4, a = [4, 1, 3, 2]))      # 输出: [4, 3, 1, 2]
    print(solution(n = 6, a = [1, 2, 3, 4, 5, 6]))  # 输出: [1, 3, 5, 2, 6, 4]

代码解析

  • 队列的初始化:我们使用 collections.deque 来初始化队列,它提供了高效的两端操作(popleft()append()),这对于本题非常合适。

  • 播放和调整歌单

    • 每次 popleft() 移除队列的第一个元素并添加到 result 列表中,表示这首歌被播放。
    • 如果队列中仍然有歌曲,调用 popleft() 将当前的第一首歌移到队列的末尾,模拟规则中的“移到最后”操作。
  • 结束条件:当队列为空时,说明所有歌曲已经播放完毕,返回 result

示例分析

  1. 示例1: 输入:n = 5, a = [5, 3, 2, 1, 4]

    • 初始队列:[5, 3, 2, 1, 4]

    • 播放顺序:

      • 播放 5,队列变为 [3, 2, 1, 4]
      • 3 移到队列末尾,队列变为 [2, 1, 4, 3]
      • 播放 2,队列变为 [1, 4, 3]
      • 1 移到队列末尾,队列变为 [4, 3, 1]
      • 播放 4,队列变为 [3, 1]
      • 3 移到队列末尾,队列变为 [1, 3]
      • 播放 1,队列变为 [3]
      • 播放 3,队列变为空。
    • 最终播放顺序为 [5, 2, 4, 1, 3]

  2. 示例2: 输入:n = 4, a = [4, 1, 3, 2]

    • 初始队列:[4, 1, 3, 2]

    • 播放顺序:

      • 播放 4,队列变为 [1, 3, 2]
      • 1 移到队列末尾,队列变为 [3, 2, 1]
      • 播放 3,队列变为 [2, 1]
      • 2 移到队列末尾,队列变为 [1, 2]
      • 播放 1,队列变为 [2]
      • 播放 2,队列变为空。
    • 最终播放顺序为 [4, 3, 1, 2]

  3. 示例3: 输入:n = 6, a = [1, 2, 3, 4, 5, 6]

    • 初始队列:[1, 2, 3, 4, 5, 6]

    • 播放顺序:

      • 播放 1,队列变为 [2, 3, 4, 5, 6]
      • 2 移到队列末尾,队列变为 [3, 4, 5, 6, 2]
      • 播放 3,队列变为 [4, 5, 6, 2]
      • 4 移到队列末尾,队列变为 [5, 6, 2, 4]
      • 播放 5,队列变为 [6, 2, 4]
      • 6 移到队列末尾,队列变为 [2, 4, 6]
      • 播放 2,队列变为 [4, 6]
      • 4 移到队列末尾,队列变为 [6, 4]
      • 播放 6,队列变为 [4]
      • 播放 4,队列变为空。
    • 最终播放顺序为 [1, 3, 5, 2, 6, 4]

时间复杂度分析

  • 队列操作:每次从队列中移除一个元素,时间复杂度是 O(1);每次将一个元素添加到队列末尾,时间复杂度也是 O(1)。
  • 总体复杂度:对于每个元素,我们会进行一次移除和一次添加,故总的时间复杂度为 O(n),其中 n 是歌单的歌曲数量。

总结

这个题目通过模拟一个简单的播放规则来考察队列的使用。通过队列的 popleftappend 操作,我们可以高效地实现规则中的歌曲播放与调整。通过这种方法,我们能够快速且准确地解决这个问题。