解题思路
1. 初始化数据结构
- ArrayList:用于存储最终的结果序列。选择
ArrayList是因为它提供了动态数组的功能,可以方便地添加元素,而且在转换成数组时非常便捷。 - Queue (LinkedList) :用于辅助处理输入数组
a中的元素。选择LinkedList作为队列的实现,因为LinkedList提供了高效的插入和删除操作,这正是队列操作所需要的。
2. 将数组元素加入队列
- 首先,遍历输入数组
a,将每个元素添加到队列中。这是为了能够利用队列的数据结构特性,即先进先出(FIFO),来实现题目所要求的特殊排序逻辑。
3. 按照规则处理队列中的元素
- 使用一个
while循环来处理队列中的元素,只要队列不为空就继续执行。 - 在每次循环中,从队列头部移除一个元素(即当前播放的第一首歌),并将其添加到
ArrayList中。 - 如果队列中还有元素,则再次从队列头部移除一个元素(即当前播放的第二首歌),但是这一次不是直接丢弃,而是将其添加回队列的尾部,以便下一次循环时再次被处理。
- 这个过程模拟了一个特殊的播放列表机制,其中第一首歌被播放后立即移除,而第二首歌被“跳过”并重新安排到播放列表的末尾。
4. 构建结果数组
- 当队列为空时,表示所有的元素都已经按照题目要求的顺序被处理完毕。此时,创建一个新的整型数组
result,其长度与原始数组a相同。 - 遍历
ArrayList,将其中的元素依次复制到result数组中。 - 同时,在控制台打印每个复制到
result数组中的元素,以便于调试或查看中间结果。
5. 返回结果
- 最后,函数返回构建好的
result数组,该数组包含了按照题目要求重新排列后的元素。
6. 代码实现
import java.util.Arrays;
import java.util.LinkedList;
import java.util.*;
public class Main {
public static int[] solution(int n, int[] a) {
// write code here
ArrayList<Integer> arrayList = new ArrayList<>();
Queue<Integer> queue = new LinkedList<>();
for(int i: a){
queue.add(i);
}
while(!queue.isEmpty()){
int firstSong = queue.poll();
arrayList.add(firstSong);
if(!queue.isEmpty()){
int currentSong = queue.poll();
queue.add(currentSong);
}
}
int[] result = new int[a.length];
for(int i = 0;i < arrayList.size();i++){
result[i] = arrayList.get(i);
System.out.println(result[i]);
}
return result;
}
}
7. 关于LinkedList类型
LinkedList 是一种双向链表数据结构,这意味着每个节点不仅包含数据,还包含指向列表中前一个节点和后一个节点的引用。这种设计使得 LinkedList 在某些操作上比其他类型的列表(如 ArrayList)更加高效,尤其是在频繁进行插入和删除操作的情况下。
主要特点
-
双向链表结构:
- 每个节点(
Node)包含三个部分:数据(element)、指向前一个节点的引用(prev)和指向后一个节点的引用(next)。 - 这种结构使得可以在任意位置高效地插入和删除节点,因为不需要移动其他节点,只需要更改相邻节点的引用即可。
- 每个节点(
-
支持快速插入和删除:
- 插入和删除操作的时间复杂度为 O(1),前提是已经找到了要操作的节点。
- 这使得
LinkedList在需要频繁插入和删除元素的场景中表现优异。
-
支持双端队列操作:
LinkedList实现了Deque接口,因此可以作为双端队列(Double-Ended Queue)使用。- 提供了多种方法来操作队列的两端,例如
addFirst、addLast、removeFirst、removeLast等。
-
随机访问效率低:
- 由于
LinkedList是链式结构,不支持随机访问。要访问某个特定索引的元素,必须从头或尾开始遍历,直到找到该元素。 - 随机访问的时间复杂度为 O(n),因此在需要频繁随机访问的场景中,
LinkedList不是最优选择。
- 由于
常用方法
-
基本操作:
add(E e):将指定元素添加到列表的末尾。add(int index, E element):将指定元素插入列表中的指定位置。remove(Object o):移除列表中第一次出现的指定元素(从头到尾遍历)。remove(int index):移除列表中指定位置的元素。get(int index):返回列表中指定位置的元素。set(int index, E element):用指定元素替换列表中指定位置的元素。
-
双端队列操作:
addFirst(E e):将指定元素插入此列表的开头。addLast(E e):将指定元素追加到此列表的末尾。removeFirst():移除并返回此列表的第一个元素。removeLast():移除并返回此列表的最后一个元素。getFirst():返回此列表的第一个元素。getLast():返回此列表的最后一个元素。