小R的随机播放顺序| 豆包MarsCode AI刷题

52 阅读4分钟

解题思路

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)更加高效,尤其是在频繁进行插入和删除操作的情况下。

主要特点

  1. 双向链表结构

    • 每个节点(Node)包含三个部分:数据(element)、指向前一个节点的引用(prev)和指向后一个节点的引用(next)。
    • 这种结构使得可以在任意位置高效地插入和删除节点,因为不需要移动其他节点,只需要更改相邻节点的引用即可。
  2. 支持快速插入和删除

    • 插入和删除操作的时间复杂度为 O(1),前提是已经找到了要操作的节点。
    • 这使得 LinkedList 在需要频繁插入和删除元素的场景中表现优异。
  3. 支持双端队列操作

    • LinkedList 实现了 Deque 接口,因此可以作为双端队列(Double-Ended Queue)使用。
    • 提供了多种方法来操作队列的两端,例如 addFirstaddLastremoveFirstremoveLast 等。
  4. 随机访问效率低

    • 由于 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():返回此列表的最后一个元素。