题目解析:小R的随机播放规则
在这个问题中,我们需要模拟一个特殊的歌曲播放顺序。小R的随机播放规则是:首先播放歌单中的第一首歌,播放后将其从歌单中移除。接下来,他会将当前歌单中的第一首歌移到歌单的最后一位,然后继续播放新的第一首歌,直到歌单为空。
给定一个歌单,任务是模拟这个播放过程,返回实际的播放顺序。
题目分析
-
输入说明:
- 输入一个整数
n,表示歌单中歌曲的数量。 - 输入一个整数列表
a,表示歌单中的歌曲,a[i]表示第 i 首歌的 ID。
- 输入一个整数
-
输出说明:
- 输出一个列表,表示实际播放的歌曲顺序。
解决思路
我们可以通过以下步骤来实现这个模拟过程:
-
将给定的歌单
a转换为一个队列(queue)。队列是一个适合模拟这种“先进先出”(FIFO)操作的数据结构。我们每次从队列的前端取出一首歌播放,然后将剩下的歌曲重新调整,按规则将当前第一首歌移动到队列的末尾。 -
使用队列的基本操作:
popleft():从队列的左端(即当前第一首歌)移除并返回该元素。append():将当前第一首歌添加到队列的末尾。
具体步骤
-
将输入列表
a转换为一个队列queue。 -
创建一个空列表
result用来存储实际的播放顺序。 -
遍历队列,直到队列为空:
- 每次从队列中取出第一首歌并添加到
result。 - 如果队列非空,将当前的第一首歌移到队列的末尾。
- 每次从队列中取出第一首歌并添加到
-
最终返回
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: 输入:
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: 输入:
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: 输入:
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 是歌单的歌曲数量。
总结
这个题目通过模拟一个简单的播放规则来考察队列的使用。通过队列的 popleft 和 append 操作,我们可以高效地实现规则中的歌曲播放与调整。通过这种方法,我们能够快速且准确地解决这个问题。