学习方法与心得 3|豆包MarsCode AI刷题

123 阅读3分钟

小R的随机播放规则分析与实现

问题描述

小R有一个特殊的随机播放规则:

  1. 从歌单中播放第一首歌,并将其移除。
  2. 如果歌单中还有歌曲,将当前的第一首歌移到歌单末尾。
  3. 重复以上步骤,直到歌单中没有歌曲。

例如,给定歌单 [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]

思路解析

这道题本质是对数组元素进行按规则的重新排列,遵循 移除+重排 的规则,直到数组为空。通过模拟整个过程,可以直接得出结果。

关键点在于:

  1. 移除第一首歌: 每次播放后从数组中移除首元素。
  2. 移动到末尾: 如果数组不为空,将当前首元素移到数组末尾。
  3. 循环直到歌单清空。

解题步骤

  1. 初始化一个空列表 result 用于存储播放顺序。

  2. 使用 while 循环遍历数组 a,每次处理一首歌。

  3. 维护一个索引 index 记录当前需要处理的首元素。

  4. 对数组 a 的操作按题意进行:

    • 移除首元素并添加到结果中。
    • 将新的首元素移到末尾(如果存在)。
  5. 返回最终结果。


代码实现

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

优化与分析

  1. 时间复杂度

    • 每次操作需要移除或添加元素,最坏情况下是 O(n)
    • 歌单中每首歌最多被处理两次,因此整体复杂度为 O(n^2)
  2. 空间复杂度

    • result 列表存储了所有歌曲,空间复杂度为 O(n)
  3. 改进优化
    使用双端队列 collections.deque 来模拟数组操作,deque 支持 O(1) 时间复杂度的 popleftappend 操作,能显著提升性能:

    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. 实战经验

通过这道题的练习,我掌握了环形数组与动态序列调整的技巧。在实际编程中,理解数据结构的特性,选择最优方案,是提升效率的关键。

希望这篇总结能对其他同学有所帮助,祝大家在刷题的道路上越走越远!