蓝桥杯高校新生编程赛第一场题解——Java

01. 小猫取名【新生编程赛】

完整解题代码:

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

public class Main {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        //在此输入您的代码...
        StringBuilder sb=new StringBuilder();
        for(int i=0;i<6;i++){
          String str1=scan.next();
          sb.append(str1.charAt(0));
        }

        String b=sb.toString();
        System.out.println(b);

        //System.out.println(sb);
   
        scan.close();
    }
}

解题思路:

1.明确目标:

本题需要将 6 个单词的首字母按顺序拼接输出。核心思路是依次读取每个单词,提取其首字符,再将这些字符拼接输出

2.读取并提取首字符:

想要实现这个功能,我们率先想到**String类的charAt(int index)方法,该方法用于获取字符串中指定索引的字符(本题中使其索引为0,便可获得首字符)。**

3.拼接输出字符:

想要快捷拼接字符,即想使用一种修改字符串的手段,我们可以想到使用StringBuilder类,其中的public StringBuffer append(String s),可以实现将指定的字符串追加到此字符序列。

4.返回输出字符串:

**使用toString() 方法返回此对象本身(它已经是一个字符串)。**最后输出完整字符串,即可解答。

(如果后续需要多次使用拼接好的字符串, 可先通过 toString() 生成 String 并保存,便于操作。

此题可直接输出原字符串)

涉及知识点:

1.String类的charAt(int index)方法

Java charAt() 方法

charAt() 方法用于返回指定索引处的字符。索引范围为从 0 到 length() - 1。

语法

复制代码
public char charAt(int index)

参数

  • index -- 字符的索引。

返回值

返回指定索引处的字符。

实例

复制代码
public class Test {
    public static void main(String args[]) {
        String s = "www.runoob.com";
        char result = s.charAt(6);
        System.out.println(result);
    }
}

以上代码输出结果为:n

2.Java StringBuffer 和 StringBuilder 类

当对字符串进行修改的时候,需要使用 StringBuffer 和 StringBuilder 类。

和 String 类不同的是,StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象。

在使用 StringBuffer 类时,每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象,所以如果需要对字符串进行修改推荐使用 StringBuffer。

StringBuilder 类在 Java 5 中被提出,它和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的(不能同步访问)。

由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。

实例:

复制代码
public class RunoobTest{
    public static void main(String[] args){
        StringBuilder sb = new StringBuilder(10);
        sb.append("Runoob..");
        System.out.println(sb);  
        sb.append("!");
        System.out.println(sb); 
        sb.insert(8, "Java");
        System.out.println(sb); 
        sb.delete(5,8);
        System.out.println(sb);  
    }
}

以上实例编译运行结果如下:

Runoob..

Runoob..!

Runoob..Java!

RunooJava!

图示原理:

然而在应用程序要求线程安全的情况下,则必须使用 StringBuffer 类。

实例:

复制代码
public class Test{
  public static void main(String[] args){
    StringBuffer sBuffer = new StringBuffer("菜鸟教程官网:");
    sBuffer.append("www");
    sBuffer.append(".runoob");
    sBuffer.append(".com");
    System.out.println(sBuffer);  
  }
}

以上实例编译运行结果:菜鸟教程官网:www.runoob.com

以下是 StringBuffer 类支持的主要方法:

序号 方法描述
1 public StringBuffer append(String s) 将指定的字符串追加到此字符序列。
2 public StringBuffer reverse() 将此字符序列用其反转形式取代。
3 public delete(int start, int end) 移除此序列的子字符串中的字符。
4 public insert(int offset, int i) 将 int 参数的字符串表示形式插入此序列中。
5 insert(int offset, String str) 将 str 参数的字符串插入此序列中。
6 replace(int start, int end, String str) 使用给定 String 中的字符替换此序列的子字符串中的字符。

3.Java toString() 方法

toString() 方法返回此对象本身(它已经是一个字符串)。

语法

复制代码
public String toString()

参数

返回值

字符串本身。

实例

复制代码
public class Test {
    public static void main(String args[]) {
        String Str = new String("WWW.RUNOOB.COM");

        System.out.print("返回值 :" );
        System.out.println( Str.toString() );
    }
}

以上程序执行结果为:返回值 :WWW.RUNOOB.COM

02. 修改编码文件【新生编程赛】

完整解题代码:

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

public class Main {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        //在此输入您的代码...
        String str=scan.next();
        System.out.println(str.replaceAll("[0-9]","Q").replaceAll("[a-z]","L"));
        scan.close();
    }
}

解题思路:

1.明确目标:

本题需要将输入字符串中的小写字母替换为 L数字替换为 Q 。核心思路是利用正则表达式批量匹配目标字符集,通过字符串替换方法完成转换,最终输出结果

2.正则替换:

  • 调用 replaceAll("[0-9]", "Q"),将所有数字(0~9)替换为 Q
  • 调用 replaceAll("[a-z]", "L"),将所有小写字母(a~z)替换为 L

(由于数字和字母是互斥的字符集,替换顺序不影响最终结果)

3.输出结果:

直接打印经过两次替换后的字符串。

涉及知识点:

1.Java replaceAll() 方法

replaceAll() 方法使用给定的参数 replacement 替换字符串所有匹配给定的正则表达式的子字符串。

语法

复制代码
public String replaceAll(String regex, String replacement)

参数

  • regex -- 匹配此字符串的正则表达式。

  • replacement -- 用来替换每个匹配项的字符串。

返回值

成功则返回替换的字符串,失败则返回原始字符串。

实例

复制代码
public class Test {
    public static void main(String args[]) {
        String Str = new String("www.google.com");
        System.out.print("匹配成功返回值 :" );
        System.out.println(Str.replaceAll("(.*)google(.*)", "runoob" ));
        System.out.print("匹配失败返回值 :" );
        System.out.println(Str.replaceAll("(.*)taobao(.*)", "runoob" ));
    }
}

以上程序执行结果为:

复制代码
匹配成功返回值 :runoob
匹配失败返回值 :www.google.com

正则表达式解析:

1. 组件解析

  • . :匹配任意单个字符(除了换行符)。
  • * :表示前面的元素可以出现 0 次或多次 。因此,.* 组合起来的意思是 "匹配任意长度的任意字符(包括空字符串)"。
  • ():正则中的 "分组",用于捕获匹配的内容(也可用于逻辑组合)。

2. 整体含义

(.*)google(.*) 的意思是:

  • 先匹配任意长度的任意字符(.*)),
  • 然后匹配字符串 "google"
  • 最后再匹配任意长度的任意字符(.*))。

简言之,这个正则是用来匹配包含 "google" 子串的任意字符串,并将 "google" 前后的所有内容都包含在匹配范围内。

03.设计师调度【新生编程赛】

完整解题代码:

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

public class three{
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        //在此输入您的代码...
        int a1=scan.nextInt();
        int a2=scan.nextInt();
        int a3=scan.nextInt();
        scan.close();

        Integer[] arr={a1,a2,a3};
        int min=(int)Collections.min(Arrays.asList(arr));
        int max=(int)Collections.max(Arrays.asList(arr));

        int mid=a1+a2+a3-max-min;
        if (mid + min <= max) {
            System.out.println(max);
        } else {
            System.out.println(mid + min);
        }

    }
}

解题思路:

1.明确目标:

题目要使三位设计师完成所有任务的总时间最短,需利用并行调度的思想。

2.贪心策略:

设定让两个任务尽可能并行执行,减少等待时间。具体策略是:将三个任务的时间排序为 x ≤ y ≤ z,最小总时间为 max(z, x + y)

3.排序处理与极值提取:

明确目标后,我们将输入的三个数存入数组,利用 Collections.minCollections.max 分别获取最小值 min和最大值 max,中间值 mid 通过 "总和 - 最小值 - 最大值" 计算得到。

4.结果计算:

比较 maxmin + mid 的大小,取较大值作为最小总时间。

  • min + mid ≤ max:总时间由最长的任务 max 决定(两个较小任务并行完成后,最长任务仍在执行,总时间为 max)。
  • min + mid > max:总时间由两个较小任务的并行时间 min + mid 决定(两个较小任务并行完成时,最长任务也已完成)。

涉及知识点:

1.集合与数组操作:

int 数组转换为 Integer 数组(因 Collections 工具类方法针对对象类型),利用 Arrays.asList 转换为列表,再通过 Collections.minCollections.max 提取极值。

(便于寻找有限个数字中的极值)

注意导入库

复制代码
import java.util.Arrays;
import java.util.Collections;

实例:

Using Collections.max() . This requires converting the array to a list first.

复制代码
import java.util.Arrays;

import java.util.Collections;



public class MaxValueCollections {

    public static void main(String[] args) {

    Integer[] arr = {3, 7, 2, 1, -4}; // Use Integer instead of int

    int max = Collections.max(Arrays.asList(arr));

    System.out.println("Maximum value: " + max);

    }

}

2.贪心算法 :

一、贪心算法的核心逻辑

贪心算法的本质是每一步都做 "当前最有利" 的选择,通过 "局部最优" 的累积,最终得到 "全局最优" 的结果。

二、本题中贪心策略的体现

在 "设计师调度" 问题中,我们的目标是最小化三个任务的总完成时间 。由于平台一次只能容纳两名设计师并行工作,因此需要让两个耗时较短的任务优先并行,这就是本题的 "局部最优选择"。

具体推导如下:假设三个任务的时间为 a, b, c,我们先将其排序为 x ≤ y ≤ zx 是最小值,z 是最大值,y 是中间值)。

  • xy 这两个较小的任务并行执行(充分利用平台的并行能力,减少等待时间)。
  • 此时总时间的判定分为两种情况:
    • x + y ≤ z:两个小任务并行完成后,最大的任务 z 仍在执行,因此总时间由 z 决定。
    • x + y > z:两个小任务并行的时间里,最大的任务 z 也已完成,因此总时间由 x + y 决定。
三、贪心性质的验证

本题满足贪心算法的两大关键性质:

  1. **贪心选择性质:**全局最优解(最小总时间)可以通过 "让两个最小任务并行" 这一局部最优选择来构造。
  2. 最优子结构性质: 总时间的最优解依赖于 "两个较小任务并行" 和 "最大任务耗时" 这两个子问题的最优解(即比较 x+yz 的大小)。

04.妈妈的菜单【新生编程赛】

完整解题代码:

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

public class Main {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        //在此输入您的代码...
        int sum=0;
        int result=0;
        for (int i=1;i<=10;i++){
          int a=scan.nextInt();
          sum+=a; 
          if(Math.abs(sum-100)<=Math.abs(result-100)){
            result=sum;
          }
        }
      System.out.println(result);
        scan.close();
    }
}

解题思路:

1.明确目标:

本题需要按顺序累加菜品的饱腹值,在每一步都判断当前累加和与100的接近程度,最终找到最接近 100(差距相同时选更大值)的累加和。核心思路是按顺序遍历所有可能的 "前 k 道菜累加和",动态更新最接近 100 的结果

2.差距比较与结果更新:

  • 利用Math.abs计算当前sum与 100 的差距,不断赋给result,计算上一步已有结果result与 100 的差距。
  • 若当前sum与 100 的差距更小,或差距相同但sum更大,则更新result为当前sum

3.遍历结束与输出:

循环结束后,通过本次sum与上一步累加的result进行对比,让result永远为最大且最接近100的累加,最后输出result作为饱腹值。

涉及知识点:

1.绝对值计算:

Math.abs方法用于计算数值的绝对值

2.贪心算法:

在 "妈妈的菜单" 问题中,我们需要在按顺序累加菜品饱腹值的过程中,动态维护 "最接近 100(差距相同时选更大值)" 的累加和。其贪心策略可拆解为以下两点:

1. 局部最优选择:每一步都更新 "当前最接近 100 的累加和"

遍历每一道菜时,我们会计算 "前 i 道菜的总饱腹值",并与已记录的 "最接近 100 的结果" 比较:

  • 若当前累加和与 100 的差距更小,则更新结果为当前累加和;
  • 若差距相同但当前累加和更大,也更新结果(因为题目要求 "吃撑一点比饿着好")。

这一步的 "局部最优" 是:在当前遍历到的所有 "前 i 道菜的和" 中,选择最接近 100 的那个

2. 全局最优的推导:局部最优的累积

由于题目规则是 "一旦不吃某道菜,后续菜都不上",因此所有可能的候选解只能是 "前 1 道菜的和、前 2 道菜的和...... 前 10 道菜的和"。

我们通过逐一遍历这些候选解 ,并在每一步都做 "局部最优选择(更新最接近 100 的结果)",最终这些局部最优的选择会累积成全局最优解------ 即所有候选解中最接近 100(或差距相同时更大)的那个。

3.贪心性质的验证

本题满足贪心算法的两大关键性质:

  • 贪心选择性质:全局最优解一定是 "前 k 道菜的和"(k∈[1,10]),而我们通过每一步的局部最优选择(更新最接近 100 的结果),可以覆盖并找到这个全局最优解。
  • 最优子结构性质:"前 k 道菜的最优解" 依赖于 "前 k-1 道菜的最优解"------ 每一步的选择都基于之前所有步骤的最优结果,从而推导当前步骤的最优选择。

05.挑选题目【新生编程赛】

完整解题代码:

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

public class Main {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        //在此输入您的代码...
        int N = scan.nextInt();
        int[] A = new int[N];
        int[] B = new int[N];
        for (int i = 0; i < N; i++) {
            A[i] = scan.nextInt();
        }
        for (int j = 0; j < N; j++) {
            B[j] = scan.nextInt();
        }
        scan.close();

        int maxDiff = 0;
        for (int i = 0; i < A.length; i++) {  
        int a = A[i]; 
        int minDiffA = Integer.MAX_VALUE;  
            for (int j = 0; j < B.length; j++) {  
              int b = B[j];  
              int diff = Math.abs(a - b);  
              if (diff < minDiffA) { 
                minDiffA = diff;
              }
            }
            if (minDiffA > maxDiff) {
                maxDiff = minDiffA;
            }
        }
      System.out.println(maxDiff);
    }
}

解题思路:

1.明确目标:

小蓝希望最终题目难度差尽可能大,小桥希望尽可能小,且两人均采取最优策略。核心思路是:

  • 小蓝遍历自己的每一道题,对每道题,小桥会选择与它差值最小的题(小桥的最优策略);
  • 小蓝在这些 "小桥的最小差值" 中,选择最大的那个(小蓝的最优策略),即为最终结果。

(误区:一开始简单认为读取数组后,只需分别找到各自题目难度中的极值,相减即得最终解果)

我一开始理解偏差,是因为忽视了这道题的核心是双方 "轮流删除自己的题目" 的博弈过程,不是 "直接留自己的最大 / 最小",需要结合双方的策略动态分析:
正确的策略逻辑

我们可以从 "小蓝的视角" 推导:

  • 小蓝遍历自己的每一道题(假设最终留下这道题);
  • 对于这道题,小桥会选择自己手中与它差值最小的题目(因为小桥要最小化差值,这是小桥的最优策略);
  • 小蓝在所有 "小桥的最小差值" 中,选择最大的那个(因为小蓝要最大化差值,这是小蓝的最优策略)。

2.循环遍历,动态博弈:

101 变量初始化:int maxDiff = 0

  • 作用:保存最终结果 ------ 小蓝在双方最优策略下能得到的最大差值。
  • 初始值设为 0,因为差值不可能为负数(用Math.abs计算,结果≥0)。

202 外层循环:遍历小蓝的每一道题(for (int i = 0; i < A.length; i++)

  • 逻辑:假设小蓝最终决定留下数组 A 中的第i道题(即a = A[i]),然后计算在这种情况下,小桥会如何应对。
  • 举例:如果 A 是[1, 10],外层循环会先处理a=1,再处理a=10

303 内层循环:为当前a找小桥的最优解(for (int j = 0; j < B.length; j++)

  • 逻辑:对小蓝留下的a,小桥会从自己的数组 B 中选一道题b,使得ab的差值最小(因为小桥的目标是 "让最终差值尽可能小")。
  • 关键变量minDiffA:记录 "小桥针对当前a能选出的最小差值"。
    • 初始化为Integer.MAX_VALUE(整数最大值),是为了确保第一次比较时,任何实际差值(≥0)都会比它小,从而能正确更新minDiffA
  • 举例:当a=10,B 是[2, 20]时:
    • 先算b=2的差值:|10-2|=8,此时minDiffA更新为 8;
    • 再算b=20的差值:|10-20|=10,比 8 大,minDiffA保持 8;
    • 因此,小桥对a=10的最优解是 8。

404 小蓝的最终选择:更新maxDiff

  • 逻辑:小蓝的目标是 "让最终差值尽可能大",所以需要在所有 "小桥的最小差值"(即每个a对应的minDiffA)中,选最大的那个。
  • 举例:小蓝的a=1时,小桥的最小差值是 1(b=2);小蓝的a=10时,小桥的最小差值是 8(b=2);因此maxDiff会从 0 更新为 8,最终输出 8。

3.核心逻辑:

使用嵌套循环 模拟了双方的动态博弈

  • 内层循环:替小桥做选择 ------ 对小蓝的每道题,找自己手中最接近的题(最小差值);
  • 外层循环:替小蓝做选择 ------ 在小桥的所有 "最小差值" 中,找最大的那个(确保自己的利益最大化)。

涉及知识点:

1.嵌套循环遍历:

外层循环遍历小蓝的每一道题 a,内层循环遍历小桥的每一道题 b,计算并记录 a 对应的 "最小差值"(小桥的最优策略)。

2.贪心策略的博弈体现

小桥的局部最优:对每个 a,选 b 使得 |a - b| 最小(minDiffA);

小蓝的全局最优:在所有 minDiffA 中,选最大的那个(maxDiff)。

3.绝对值与极值处理

Math.abs 计算差值的绝对值,用 Integer.MAX_VALUE 初始化 "最小差值" 以确保后续更新逻辑正确。

相关推荐
百花~5 小时前
JVM(Java虚拟机)~
java·开发语言·jvm
每天进步一点点dlb5 小时前
JVM中的垃圾回收算法和垃圾回收器
jvm·算法
tant5 小时前
声明式事务@Transactional失效场景研究
java
沐苏瑶5 小时前
PHP反序列化漏洞
java·开发语言
我爱鸢尾花5 小时前
CNN基础理论讲解及Python代码复现
人工智能·python·深度学习·神经网络·算法·机器学习·cnn
大数据张老师5 小时前
数据结构——二叉搜索树
数据结构·算法·二叉搜索树·查找·关键路径
该用户已不存在5 小时前
写了这么多年Java,这几个神仙技巧你用过吗?
java·后端
小王不爱笑1325 小时前
Java 核心知识点查漏补缺(二)
java·开发语言
Lacrimosa&L5 小时前
OS_2 进程与线程(进程管理)
java·开发语言