个人题解|小R的随机播放顺序

153 阅读4分钟

问题描述

小R有一个特殊的随机播放规则。给定一个歌单,首先播放歌单中的第一首歌,播放后将其从歌单中移除。如果歌单中还有歌曲,则会将当前播放的第一首歌移到最后一首。这个过程会一直重复,直到歌单中没有任何歌曲。

例如,给定歌单 [5, 3, 2, 1, 4],按照规则的播放顺序是 [5, 2, 4, 1, 3]

保证歌曲中的id两两不同。

解题思路

此题本质上是对一个列表进行特定规则的操作。具体步骤可以概括为:

  1. 播放并移除:每次从歌单的头部播放一首歌,并将其从歌单中移除。
  2. 移到最后:如果歌单中还有歌曲,则将当前第一首歌移到歌单的最后。
  3. 重复直到空:上述操作会持续,直到歌单为空。

根据描述,首先从歌单中移除第一首歌,然后将剩余的第一首歌放到队列的末尾,直到歌单为空。因此,可以使用队列来模拟这一过程,因为队列的特性正符合"先入先出"(FIFO),适合解决这个问题。

数据结构选择

为了高效地模拟这个过程,我们可以使用一个队列(std::queue)来存储歌曲的顺序。

队列的特性是先进先出(FIFO),非常适合模拟歌曲的播放和移动操作。

具体步骤

  1. 初始化队列:我们将给定的歌单看作一个队列。
  2. 反复操作:每次从队列中移除第一个元素(播放),然后把它放到队列的末尾(如果队列不为空)。
  3. 输出播放顺序:我们通过一个数组收集播放的顺序,直到队列为空。
#include <iostream>
#include <vector>
#include<queue>

std::vector<int> solution(int n, std::vector<int> a) {
    std::vector<int> result;  // 用于存储最终的播放顺序
    std::queue<int> q;        // 用于模拟播放过程的队列

    // 将所有歌曲ID放入队列中
    for (int i = 0; i < n; ++i) {
        q.push(a[i]);
    }

    while (!q.empty()) {
        // 取出队列中的第一首歌并播放
        int current = q.front();
        q.pop();
        result.push_back(current);

        // 如果队列中还有歌曲,将当前队列的第一首歌移到队列的末尾
        if (!q.empty()) {
            int next = q.front();
            q.pop();
            q.push(next);
        }
    }
       return result;
}
  
int main(){
    std::vector<int> result1 = {5, 2, 4, 1, 3};
    std::vector<int> result2 = {4, 3, 1, 2};
    std::vector<int> result3 = {1, 3, 5, 2, 6, 4};

    std::cout << (solution(5, {5, 3, 2, 1, 4}) == result1) << std::endl;
    std::cout << (solution(4, {4, 1, 3, 2}) == result2) << std::endl;
    std::cout << (solution(6, {1, 2, 3, 4, 5, 6}) == result3) << std::endl;
    return 0;

}

代码分析

  1. 导入队列:使用 collections.deque 来实现队列。deque 是一个双端队列,支持从两端进行高效的插入和删除操作。

  2. 播放逻辑

    • 通过 queue.popleft() 从队列中取出并播放第一首歌(等同于移除队列的第一个元素)。
    • 然后通过 queue.append() 将当前播放的歌移到队列的末尾。append 操作将元素添加到队列的尾部。
  3. 循环播放:循环的条件是队列非空,在队列为空之前持续执行播放和移歌到队尾的操作。直到队列为空,整个播放过程结束。

  4. 返回结果:最终返回一个列表 result,该列表记录了歌曲的播放顺序。

代码总结

  • 通过使用队列数据结构,能够高效地实现歌曲的播放与重新排序。deque 提供了高效的从队头取出和从队尾添加的操作,保证了时间复杂度的优化。
  • 该解法的时间复杂度为 O(n) ,其中 n 是歌单的长度。每次操作中,每个元素最多会被添加和移除一次,因此总操作数为 2n,即时间复杂度是线性的。
  • 空间复杂度为 O(n) ,我们使用了额外的队列来存储歌单。

总结

本题的关键是模拟歌曲的播放过程,使用队列来管理歌曲的顺序是最合适的选择。队列的先进先出(FIFO)特性非常契合题目中的需求,通过合理使用 deque 数据结构,我们可以高效地实现这一过程。