NO.24 小R的随机播放顺序
问题描述
小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]
题目解析
- 创建一个结果列表来保存歌曲的播放顺序。
- 循环处理歌单,直到歌单为空:
- 播放当前第一首歌(移除第一首歌并记录到结果列表中)。
- 如果歌单还有剩余的歌曲,将新的第一首歌移动到歌单末尾。
- 返回结果列表。
测试案例分析
以 n = 5, a = [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移到末尾,变为[3]。 - 播放
3,剩余列表为空。
最终顺序为 [5, 2, 4, 1, 3]。
定义变量如下:
- 播放结果记录:rst
- 当前播放索引:idx
- 当前索引歌曲:tmp
代码实现1
#include <iostream>
#include <vector>
using namespace std;
std::vector<int> solution(int n, std::vector<int> a) {
vector<int> rst; //存储播放结果顺序
int idx = 0; //当前播放索引
while (!a.empty()) { //循环直到歌单为空
// 播放当前第一首歌
rst.push_back(a[idx]); //将当前播放歌曲加入结果记录
a.erase(a.begin() + idx); //从歌单中移除这首歌
// 若还有歌,将当前第一首歌移到最后
if (!a.empty()) {
idx %= a.size(); //调整索引取模确保索引不会越界
int tmp = a[idx]; //记录当前索引处的歌曲
a.erase(a.begin() + idx); //将当前索引处的歌曲移除
a.push_back(tmp); //将这首歌添加到歌单末尾
}
}
return rst; //返回最终的播放顺序
}
注意:
- 索引在使用时可能超出数组的范围,故需要 idx %= a.size() 重新调整 idx 避免出现数组越界的情况。
- 另一解法:若为避免频繁使用
erase和push_back,则可以考虑直接修改索引,降低复杂度。
代码实现2
#include <iostream>
#include <vector>
using namespace std;
std::vector<int> solution(int n, std::vector<int> a) {
vector<int> rst; //存储播放结果顺序
int idx = 0; //当前播放索引
while (!a.empty()) { // 循环直到歌单为空
rst.push_back(a[idx]); // 将当前索引处的歌曲加入结果列表
a.erase(a.begin() + idx); // 从歌单中移除这首歌
if (!a.empty()) { // 歌单中仍有剩余歌曲
idx = (idx + 1) % a.size(); // 更新索引,将首歌移动到末尾(以循环方式)
}
}
return rst; // 返回最终的播放顺序
}