题目:小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]
解题思路
-
理解问题:
- 我们需要模拟一个播放顺序,每次播放第一首歌,然后将其移除。
- 如果还有歌曲,将当前第一首歌移到最后一首。
- 重复上述过程,直到所有歌曲都被播放。
-
数据结构选择:
- 使用队列(Queue)来模拟播放顺序。队列的特性是先进先出(FIFO),非常适合模拟播放和移动操作。
-
算法步骤:
- 将所有歌曲加入队列。
- 循环直到队列为空:
- 播放当前队列的第一首歌(即出队)。
- 如果队列不为空,将当前第一首歌移到队列末尾(即再次出队并入队)。
-
代码实现:
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
public class Main {
public static int[] solution(int n, int[] a) {
// write code here
Queue<Integer> q = new LinkedList<>();
int index = 0;
for (int song : a) {
q.offer(song);
}
while(!q.isEmpty()){
// 播放当前第一首歌
a[index++] = q.poll();
// 如果队列不为空,将当前第一首歌移到队列末尾
if (!q.isEmpty()) {
q.offer(q.poll());
}
}
return a;
}
public static void main(String[] args) {
System.out.println(Arrays.equals(solution(5, new int[]{5, 3, 2, 1, 4}), new int[]{5, 2, 4, 1, 3}));
System.out.println(Arrays.equals(solution(4, new int[]{4, 1, 3, 2}), new int[]{4, 3, 1, 2}));
System.out.println(Arrays.equals(solution(6, new int[]{1, 2, 3, 4, 5, 6}), new int[]{1, 3, 5, 2, 6, 4}));
}
}
时间复杂度:O(n)
空间复杂度:O(n)
关键点总结
- 队列的使用:利用队列的先进先出特性,模拟歌曲的播放和移动操作。
- 循环控制:通过
while循环控制播放过程,直到队列为空。 - 边界条件:确保在队列不为空时才进行歌曲的移动操作。
心得
- 直接把数组放到队列里实现起来比较简单。
- 循环里面一开始我的思路是两个元素一组,一个出队,一个放到队尾,但是还要处理奇数个和偶数个元素两种情况。问了AI,看到AI给出的代码发现自己想复杂了,直接在while循环里操作就好。
- AI给出的代码中,先出队再入队直接用一句
q.offer(q.poll())完事,代码十分简洁巧妙,学到了~