第十六届蓝桥杯省赛 C 组——Java题解1(链表知识点)

5. 冷热数据队列

(1)完整代码:

复制代码
import java.util.Scanner;
import java.util.LinkedList;
// 1:无需package
// 2: 类名必须Main, 不可修改

public class Main {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        //在此输入您的代码...
        
        int n1=scan.nextInt();
        int n2=scan.nextInt();
        int m=scan.nextInt();

        int[] arr=new int[m];
        for(int i=0;i<m;i++){
            arr[i]=scan.nextInt();
        }
        scan.close();

        LinkedList<Integer> q1=new LinkedList<>();
        LinkedList<Integer> q2=new LinkedList<>();

        //遍历输入的所有数
        for(int v:arr) {
            //情况2:数据在q1,移到q1首部
            if (q1.contains(v)) {
                q1.remove((Integer) v);
                q1.addFirst(v);
                // 检查q1是否溢出
                if (q1.size() > n1) {
                    int removed = q1.removeLast();
                    //若q2未满,移到q2首部
                    if (q2.size() < n2) {
                        q2.addFirst(removed);
                    }
                }
            } else if (q2.contains(v)) {
                //情况2:数据在q2中,移到q1首部
                q2.remove((Integer) v);
                q1.addFirst(v);
                //检测q1是否溢出
                if (q1.size() > n1) {
                    int removed = q1.removeLast();
                    if (q2.size() < n2) {
                        q2.addFirst(removed);
                    }
                }
            } else {
                //情况1:数据不在任何队列,添加到q2首部
                q2.addFirst(v);
                //检查q2是否溢出
                if (q2.size() > n2) {
                    q2.removeLast();
                }
            }
        }
        // 输出q1的元素
        for (int i = 0; i < q1.size(); i++) {
            System.out.print(q1.get(i));
            if (i != q1.size() - 1) {
                System.out.print(" ");
            }
        }
        System.out.println();

        // 输出q2的元素
        for (int i = 0; i < q2.size(); i++) {
            System.out.print(q2.get(i));
            if (i != q2.size() - 1) {
                System.out.print(" ");
            }
        }
        System.out.println();
    }
}

(2)解题思路:

1.明确目标:

本题要求模拟 "冷热数据队列" 的操作过程,该队列由热数据队列 q₁(长度 n₁)冷数据队列 q₂(长度 n₂) 组成。那么我们就很容易想到使用链表的知识,可以比较方便的解决。

2.剖析逻辑:

使用LinkedList 模拟两个队列,设队列中数据为**v,**按访问顺序逐个处理数据,分三种情况实现规则逻辑,即

情况 1:v在 q₁中
情况 2:v在 q₂中
情况 3:v不在 q₁和 q₂中

3.分块拿下:

情况 1:v在 q₁中
复制代码
if (q1.contains(v)) {
    q1.remove((Integer) v);   // 从q₁中删除v
    q1.addFirst(v);           // 移到q₁首部
    // 检查q₁是否溢出
    if (q1.size() > n1) {
        int removed = q1.removeLast();  // 淘汰q₁尾部
        // 若q₂未满,将淘汰数据移到q₂首部
        if (q2.size() < n2) {
            q2.addFirst(removed);
        }
    }
}
  • 逻辑:先删除 q₁中的v,再将其插入 q₁首部;若 q₁长度超过n₁,删除尾部元素,若 q₂未满则将该元素插入 q₂首部。
情况 2:v在 q₂中
复制代码
else if (q2.contains(v)) {
    q2.remove((Integer) v);   // 从q₂中删除v
    q1.addFirst(v);           // 移到q₁首部
    // 检查q₁是否溢出
    if (q1.size() > n1) {
        int removed = q1.removeLast();
        if (q2.size() < n2) {
            q2.addFirst(removed);
        }
    }
}
  • 逻辑:先删除 q₂中的v,再将其插入 q₁首部;后续溢出处理同情况 1。
情况 3:v不在 q₁和 q₂中
复制代码
else {
    q2.addFirst(v);  // 插入q₂首部
    // 检查q₂是否溢出
    if (q2.size() > n2) {
        q2.removeLast();  // 淘汰q₂尾部
    }
}
  • 逻辑:将v插入 q₂首部;若 q₂长度超过n₂,删除尾部元素。

(3)涉及知识点:

1. 输入处理:

复制代码
Scanner scan = new Scanner(System.in);
int n1 = scan.nextInt();
int n2 = scan.nextInt();
int m = scan.nextInt();
int[] arr = new int[m];
for (int i = 0; i < m; i++) {
    arr[i] = scan.nextInt();
}
scan.close();
  • 知识点:Scanner类的输入读取,数组存储访问序列。
  • 作用:获取 q₁长度n₁、q₂长度n₂、操作次数m和具体访问的m个数据页。

2. 队列初始化:

复制代码
LinkedList<Integer> q1 = new LinkedList<>();
LinkedList<Integer> q2 = new LinkedList<>();
  • 知识点:LinkedList的初始化。LinkedList是双向链表结构,支持O (1) 时间复杂度的头部插入(addFirst)、尾部删除(removeLast) ,且提供containsremove(Object)等方法,适合模拟队列的动态操作。

3. 输出队列内容:

复制代码
// 输出q1
for (int i = 0; i < q1.size(); i++) {
    System.out.print(q1.get(i));
    if (i != q1.size() - 1) {
        System.out.print(" ");
    }
}
System.out.println();

// 输出q2
for (int i = 0; i < q2.size(); i++) {
    System.out.print(q2.get(i));
    if (i != q2.size() - 1) {
        System.out.print(" ");
    }
}
System.out.println();
  • 逻辑:遍历 q₁和 q₂,逐个输出元素,元素间用空格分隔。

(4)总结:

啵主认为,本题对链表操作的考察较为全面,将之前学习的链表的增删这一块的知识点融入的很好,有很好的练习效果。其中复习的知识点包括:

  • 数据结构:LinkedList的使用(头部插入、尾部删除、元素操作)。
  • 流程控制:多分支条件判断(if-else if-else)和循环遍历。
相关推荐
roman_日积跬步-终至千里1 小时前
【Java并发】多线程/并发问题集
java·开发语言
独断万古他化1 小时前
【算法通关】前缀和:从一维到二维、从和到积,核心思路与解题模板
算法·前缀和
loui robot1 小时前
规划与控制之局部路径规划算法local_planner
人工智能·算法·自动驾驶
格林威1 小时前
Baumer相机金属焊缝缺陷识别:提升焊接质量检测可靠性的 7 个关键技术,附 OpenCV+Halcon 实战代码!
人工智能·数码相机·opencv·算法·计算机视觉·视觉检测·堡盟相机
それども1 小时前
什么是MalformedStreamException,和WebKitFormBoundary有什么关系
java
你撅嘴真丑2 小时前
第八章 - 贪心法
开发语言·c++·算法
VT.馒头2 小时前
【力扣】2625. 扁平化嵌套数组
前端·javascript·算法·leetcode·职场和发展·typescript
wanghu20242 小时前
AT_abc443_C~E题题解
c语言·算法
思想在飞肢体在追2 小时前
Springboot项目配置Nacos
java·spring boot·后端·nacos
cyforkk2 小时前
09、Java 基础硬核复习:异常处理(容错机制)的核心逻辑与面试考点
java·数据库·面试