小R的随机播放规则分析与实现
问题描述
小R有一个特殊的随机播放规则:
- 从歌单中播放第一首歌,并将其移除。
- 如果歌单中还有歌曲,将当前的第一首歌移到歌单末尾。
- 重复以上步骤,直到歌单中没有歌曲。
例如,给定歌单 [5, 3, 2, 1, 4],实际播放顺序为 [5, 2, 4, 1, 3]。
输入
n:歌单的长度。a:包含n首歌的数组,保证每首歌的id唯一。
输出
返回歌单按照规则播放后的顺序。
示例
输入:
n = 5, a = [5, 3, 2, 1, 4]
输出:
[5, 2, 4, 1, 3]
输入:
n = 4, a = [4, 1, 3, 2]
输出:
[4, 3, 1, 2]
输入:
n = 6, a = [1, 2, 3, 4, 5, 6]
输出:
[1, 3, 5, 2, 6, 4]
思路解析
这道题本质是对数组元素进行按规则的重新排列,遵循 移除+重排 的规则,直到数组为空。通过模拟整个过程,可以直接得出结果。
关键点在于:
- 移除第一首歌: 每次播放后从数组中移除首元素。
- 移动到末尾: 如果数组不为空,将当前首元素移到数组末尾。
- 循环直到歌单清空。
解题步骤
-
初始化一个空列表
result用于存储播放顺序。 -
使用
while循环遍历数组a,每次处理一首歌。 -
维护一个索引
index记录当前需要处理的首元素。 -
对数组
a的操作按题意进行:- 移除首元素并添加到结果中。
- 将新的首元素移到末尾(如果存在)。
-
返回最终结果。
代码实现
python
def solution(n: int, a: list) -> list:
result = [] # 存储最终的播放顺序
while len(a) > 0:
# 播放当前第一首歌并移除
result.append(a[0])
a.pop(0)
# 如果还有剩余歌曲,将当前首歌移到末尾
if len(a) > 0:
a.append(a[0])
a.pop(0)
return result
优化与分析
-
时间复杂度
- 每次操作需要移除或添加元素,最坏情况下是
O(n)。 - 歌单中每首歌最多被处理两次,因此整体复杂度为
O(n^2)。
- 每次操作需要移除或添加元素,最坏情况下是
-
空间复杂度
result列表存储了所有歌曲,空间复杂度为O(n)。
-
改进优化
使用双端队列collections.deque来模拟数组操作,deque支持 O(1) 时间复杂度的popleft和append操作,能显著提升性能:python from collections import deque def solution(n: int, a: list) -> list: result = [] queue = deque(a) while len(queue) > 0: result.append(queue.popleft()) # 播放当前第一首歌 if len(queue) > 0: queue.append(queue.popleft()) # 将当前第一首歌移到末尾 return result
知识总结与心得
1. 模拟问题的解题技巧
模拟题通常直接遵循问题规则操作,虽然时间复杂度较高,但容易实现和验证正确性。
2. 数据结构选择的重要性
在需要频繁插入和移除操作的场景中,deque 是非常高效的选择,能显著降低复杂度。
3. 实战经验
通过这道题的练习,我掌握了环形数组与动态序列调整的技巧。在实际编程中,理解数据结构的特性,选择最优方案,是提升效率的关键。
希望这篇总结能对其他同学有所帮助,祝大家在刷题的道路上越走越远!