问题描述
小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. 如何高效地调整歌单顺序?
直接用列表操作(如 pop(0))移除第一首歌需要移动后续所有元素,效率较低。可以使用队列结构来实现高效的队首移除和队尾添加。
2. 如何判断播放结束?
当歌单为空时,停止操作。
代码实现
使用列表的解法
def solution(n, a):
result = []
while a:
# 播放当前第一首歌
result.append(a.pop(0))
# 若还有歌曲,调整顺序
if a:
a.append(a.pop(0))
return result
使用队列的优化解法
from collections import deque
def solution(n, a):
playlist = deque(a) # 使用双端队列初始化歌单
result = []
while playlist:
# 播放当前第一首歌
result.append(playlist.popleft())
# 若还有歌曲,调整顺序
if playlist:
playlist.append(playlist.popleft())
return result
知识点总结
1. 队列的应用
collections.deque 是 Python 中的双端队列,支持高效的队首移除(popleft)和队尾添加(append),非常适合实现类似“循环队列”的操作。
2. 时间复杂度分析
- 列表实现:移除第一首歌(
pop(0))的时间复杂度为 ,总复杂度为 。 - 队列实现:
popleft和append均为 ,总复杂度为 。
3. 边界条件处理
- 若歌单为空,无需任何操作,直接返回空列表。
- 输入数据保证合法性,无需额外验证。
4. 提前终止优化
由于操作始终处理队列的首尾,不存在提前终止的可能性,完整遍历歌单是必需的。
思考与优化
1. 其他数据结构的实现
若歌单非常大,可以考虑用链表来实现类似操作,节省内存。
2. 更复杂的规则
可以扩展到更复杂的随机播放规则,例如每次移动两首歌到队尾,或者按照一定优先级调整播放顺序等。