PTA上的练习复盘

java01 编程题作业感悟:

可以用ai指导自己怎么调试,但是不要把调代码这过程里面的精华交给ai,就是自己去修正错误不能让ai代劳!~~~

1 scanner.close()

Scanner *** = new Scanner(System.in);

***.close();

---------------------------------------------------------------------------------------------------------------------------------

所以后面真的要close的是这个***哦,以前我都会把***写成scanner,还以为所有都是用scanner关闭?!

***表示我自己取的一个变量名

2 其实同scanner输入的变量类型可以一起定义

前面我写的是Scanner sc = new Scanner(System.in);

int a = sc.nextInt();

int b = sc.nextInt();

其实也可以写成

int a = sc.nextInt(),b = sc.nextInt();

3 调试打印方法

例如第一道编程题目里面的——————————————————————————————

调试语句 System.out.println("当前i=" + i + ", sum=" + sum);

case 标签的值不需要连续,也不需要按顺序排列。它们可以是任意离散的值

常见误区对比

❌ 错误认知
// 误以为 case 必须连续(如 1, 2, 3...)
switch (num) {case 1:  // 正确case 2:  // 正确case 3:  // 正确case 5:  // ❌ 误以为不允许“跳过”4printf("Number is 1-3 or 5");break;
}
✅ 正确写法
// case 值可以是任意离散值
switch (num) {case 1:    // 允许case 10:   // 允许case 100:  // 允许printf("Number is 1, 10, or 100");break;case 5:    // 位置随意,不影响逻辑printf("Number is 5");break;
}

关键点

  1. 值的独立性:每个 case 标签只需要与 switch 表达式的类型兼容(如整数、枚举、字符串等)。
  2. 顺序无关性case 标签的顺序不影响匹配逻辑,匹配是通过值直接跳转的。
  3. 合并规则:连续的 case 标签(无代码间隔)会共享同一个执行块。

5 直观感受自己的不足吧,对比解法!

好的,我将对比分析你的代码与最优雅解法之间的差异,帮助你理解如何优化代码结构和逻辑表达:

你的原始代码(优化后)

java

public class Demo1_2 {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int limit = scanner.nextInt(),speed = scanner.nextInt();switch (test(limit, speed)) {case 0:System.out.println("Congratulations, you are within the speed limit!");break;case 1:System.out.println("You are speeding and your fine is 100.");break;case 2:System.out.println("You are speeding and your fine is 270.");break;case 3:System.out.println("You are speeding and your fine is 500.");break;}scanner.close();}//我想用switch case语句来实现,需要怎么做?/*一个朴素的想法就是将不同的类型对应其规定为case*/public static int test(int a , int b){int fine = 0;int c =b-a;if(c>= 1&&c<= 20){fine =1;}else if(c>= 21&&c<= 30){fine =2;}else if(c>=31){fine =3;}return fine;}

最优雅解法的核心逻辑

java

int overSpeed = actualSpeed - speedLimit;
if (overSpeed <= 0) {System.out.println("未超速");
} else if (overSpeed <= 20) {System.out.println("罚款100");
} else if (overSpeed <= 30) {System.out.println("罚款270");
} else {System.out.println("罚款500");
}

对比分析

  1. 函数封装 vs 直接处理

    • 你的代码:将逻辑封装在独立函数中,通过返回值(0-3)间接映射罚款金额。这种设计提高了代码复用性,但增加了函数调用的复杂度。
    • 优雅解法:直接在 main 方法中处理逻辑,减少了函数调用层级,代码更扁平化。
  2. 条件判断的简洁性

    • 你的代码:使用 c >= 1 && c <= 20 等多条件组合,覆盖每个区间的边界值。
    • 优雅解法:利用条件的互斥性,通过 overSpeed <= 20 → overSpeed <= 30 → 否则 的顺序,隐式覆盖边界值,减少了条件复杂度。
  3. 边界值处理

    • 你的代码:显式包含边界值(如 c >= 21 && c <= 30),逻辑更严谨但代码稍冗长。
    • 优雅解法:通过条件顺序(如先判断 <=20 再判断 <=30)隐式处理边界,代码更简洁。
  4. 变量命名

    • 你的代码:使用 abc 作为参数和中间变量,语义不明确。
    • 优雅解法:使用 speedLimitactualSpeedoverSpeed,代码可读性更高。

优雅解法的优势

  1. 更少的抽象层次:避免了额外的函数封装和返回值映射,直接输出结果,符合 “最小化抽象” 原则。
  2. 自然的条件顺序:利用条件的互斥性,按数值范围从小到大判断,逻辑更直观。
  3. 更清晰的变量命名:直接反映业务含义(限速、实际速度、超速值),减少理解成本。

你的代码的优势

  1. 可复用性:独立的 test 函数便于在其他场景中复用。
  2. 扩展性:若后续需要增加更多罚款等级,你的代码结构更易于扩展(只需修改函数内部逻辑)。

总结建议

=========================================================================

  • 优先选择简洁性:对于简单问题(如本题),直接在 main 方法中处理逻辑更符合 “KISS 原则”(保持简单愚蠢)。
  • 权衡复用性:若逻辑可能在多处使用,封装成独立函数更合理。
  • 优化变量命名:使用有明确语义的变量名(如 overSpeed)提升可读性。
  • 简化条件判断:利用条件的互斥性,通过顺序判断隐式处理边界值。

6 在java里面我要输入多组数据,每组数据进行一样的处理,在这个输入的代码块要怎么写?

在 Java 中,处理多组输入数据并对每组数据进行相同操作时,你可以使用循环结合 Scanner 类来实现。以下是几种常见的实现方式:

1. 已知输入组数

如果题目明确告诉你有多少组数据,可以先读取组数,再用循环处理每组数据:

java

import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int n = scanner.nextInt(); // 读取数据组数for (int i = 0; i < n; i++) {// 读取每组数据(示例:读取两个整数)int a = scanner.nextInt();int b = scanner.nextInt();// 处理数据(示例:输出两数之和)System.out.println(a + b);}scanner.close();}
}

2. 未知输入组数,以特定条件结束(如输入 0 结束)

如果题目没有明确告诉你有多少组数据,但指定了结束条件,可以使用 while 循环:

java

import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);while (true) {int a = scanner.nextInt();int b = scanner.nextInt();// 判断是否为结束条件(示例:a和b都为0时结束)if (a == 0 && b == 0) {break;}// 处理数据System.out.println(a + b);}scanner.close();}
}

3. 未知输入组数,以文件结束符(EOF)结束

在控制台中,Windows 用户可以按 Ctrl+Z,Linux/Mac 用户可以按 Ctrl+D 来模拟 EOF:

java

import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);while (scanner.hasNext()) {int a = scanner.nextInt();int b = scanner.nextInt();// 处理数据System.out.println(a + b);}scanner.close();}
}

4. 每行包含多个数据,处理整行

如果每行包含多个数据,并且需要将整行作为一个字符串处理,可以使用 scanner.nextLine()

java

import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);while (scanner.hasNextLine()) {String line = scanner.nextLine();// 处理整行数据(示例:分割字符串并求和)String[] parts = line.split(" ");int sum = 0;for (String part : parts) {sum += Integer.parseInt(part);}System.out.println(sum);}scanner.close();}
}

关键说明:

  • Scanner 类:用于从标准输入(控制台)读取数据。
  • 循环结构:根据题目要求选择 for 循环(已知组数)或 while 循环(未知组数)。
  • 结束条件:通过判断特定值(如 0)或文件结束符(EOF)来终止循环。
  • 数据读取:使用 nextInt()nextLine() 等方法读取不同类型的数据。

7 hasNextline是什么用法?(前面提到的)

在 Java 中,Scanner.hasNextLine() 是 Scanner 类的一个方法,用于检查输入源中是否还有下一行数据可读。它通常与 Scanner.nextLine() 方法结合使用,用于逐行读取文本输入。

基本用法

hasNextLine() 返回一个布尔值:

  • true如果输入源中还有下一行(即使是空白行)
  • false:如果输入源已结束(例如,用户按下了 Ctrl+D(Linux/Mac)或 Ctrl+Z(Windows))。
示例 1:逐行读取输入

java

import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);// 循环读取每一行,直到输入结束while (scanner.hasNextLine()) {String line = scanner.nextLine();  // 读取整行文本System.out.println("你输入的是:" + line);}scanner.close();}
}

运行效果

输入:Hello World
输出:你输入的是:Hello World
输入:Java is cool
输出:你输入的是:Java is cool
(用户按 Ctrl+D 结束输入)

与其他方法的区别

  1. hasNextLine() vs hasNext()

    • hasNextLine():检查是否还有下一行(无论行内是否有内容)。
    • hasNext():检查是否还有下一个标记(默认以空格分隔)。

    java

    // 输入:Hello World\nJava is cool
    scanner.hasNext();     // true(下一个标记是 "Hello")
    scanner.hasNextLine(); // true(下一行是 "Hello World")
    
  2. nextLine() vs next()

    • nextLine():读取一整行(包括换行符),返回的字符串不含换行符。
    • next():读取下一个标记(遇到空格、制表符或换行符停止)。

常见场景

场景 1:处理多行输入

java

// 输入:
// 1 2 3
// 4 5 6
// 7 8 9Scanner scanner = new Scanner(System.in);
while (scanner.hasNextLine()) {String line = scanner.nextLine();String[] numbers = line.split(" ");for (String num : numbers) {System.out.println(Integer.parseInt(num));}
}
场景 2:跳过空行

java

while (scanner.hasNextLine()) {String line = scanner.nextLine();if (!line.isEmpty()) {  // 忽略空行System.out.println("处理:" + line);}
}

注意事项

  1. 避免混用 nextLine() 和其他 nextXxx() 方法

    java

    // 错误示例:
    int num = scanner.nextInt();  // 读取整数后,换行符仍留在缓冲区
    String line = scanner.nextLine();  // 直接读取了剩余的换行符,导致跳过输入// 正确做法:
    int num = scanner.nextInt();
    scanner.nextLine();  // 手动消耗掉换行符
    String line = scanner.nextLine();
    
  2. 输入结束条件

    • 在控制台中,用户需要手动触发结束(Ctrl+D 或 Ctrl+Z)。
    • 如果从文件读取,文件结束时 hasNextLine() 自动返回 false

总结

hasNextLine() 是逐行读取输入的关键方法,适用于:

  • 处理多行文本(如文件内容、多行输入)。
  • 需要整行处理的场景(如字符串分割、正则匹配)。
  • 配合 while 循环实现连续读取,直到输入结束。

 8 最大公约数的算法思路

GCD(最大公约数)是指能够同时整除两个数的最大正整数。计算 GCD 最常用的方法是欧几里得算法(辗转相除法),其核心思想是:

对于两个数 a 和 b(a > b),它们的 GCD 等于 b 和 a% b 的 GCD,递归或迭代这个过程直到余数为 0。

欧几里得算法步骤:

  1. 用较大数除以较小数,得到余数。
  2. 用较小数除以余数,得到新的余数。
  3. 重复步骤 2,直到余数为 0。此时的除数就是 GCD。
示例:计算 GCD (48, 18)
  • 48 ÷ 18 = 2 余 12 → GCD (48, 18) = GCD (18, 12)
  • 18 ÷ 12 = 1 余 6 → GCD (18, 12) = GCD (12, 6)
  • 12 ÷ 6 = 2 余 0 → GCD (12, 6) = 6
  • 最终结果:GCD (48, 18) = 6

代码实现(Java):

java

// 方法1:递归实现
public static int gcd(int a, int b) {if (b == 0) {return a;}return gcd(b, a % b);
}// 方法2:迭代实现(更高效)
public static int gcd(int a, int b) {while (b != 0) {int temp = b;b = a % b;a = temp;}return a;
}

关键点:

  • 递归逻辑gcd(a, b) = gcd(b, a % b),直到b为 0。
  • 迭代逻辑:用临时变量存储中间值,不断更新ab直到余数为 0。

9 有关最大公约数最小公倍数的代码修正历程 

关键改进点

  1. 移除冗余的首行读取

    java

    // 删除了循环前的这两行
    // int x = scanner.nextInt();
    // int y = scanner.nextInt();
    
  2. 使用 trim() 处理首尾空格

trim是java里面很好的内置方法哦~~!

  1. java

    String line = scanner.nextLine().trim();
    
  2. 空行检查

    java

    if (line.isEmpty()) continue;
    

10 对比我的修正代码和优雅代码,感受进步

以下是一个更简洁优雅的标准答案,我会标注与你代码的主要区别:

优雅版代码

import java.util.Scanner;public class Demo1_3 {public static void main(String[] args) {try (Scanner scanner = new Scanner(System.in)) { // try-with-resources自动关闭资源while (scanner.hasNextLine()) {String[] parts = scanner.nextLine().trim().split("\\s+"); // 使用\s+处理多个空格int a = Integer.parseInt(parts[0]);int b = Integer.parseInt(parts[1]);System.out.printf("%d %d%n", gcd(a, b), lcm(a, b)); // 格式化输出}} catch (Exception e) {System.err.println("输入格式错误: " + e.getMessage()); // 异常处理}}// 使用递归实现GCD (更简洁)public static int gcd(int a, int b) {return b == 0 ? a : gcd(b, a % b);}public static int lcm(int a, int b) {return Math.abs(a * b) / gcd(a, b); // 处理负数情况}
}

我的代码

import java.util.Arrays;
import java.util.Scanner;
public class {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);while (scanner.hasNextLine()) {String line = scanner.nextLine().trim();  // 读取整行并去除首尾空格if (line.isEmpty()) continue; // 跳过空行//System.out.println("读取的行: " + line);// 分割输入的两个整数String[] parts = line.split(" ");int a = Integer.parseInt(parts[0]);int b = Integer.parseInt(parts[1]);//System.out.println("分割后的部分: " + Arrays.toString(parts));// 计算GCD和LCMint gcdResult = gcd(a, b);int lcmResult = lcm(a, b);// 输出结果System.out.println(gcdResult + " " + lcmResult);}}public static int lcm(int a, int b){// 先除后乘避免溢出return a / gcd(a, b) * b;}public static int gcd(int a,int b) {while (b != 0) {int temp = b;b = a % b;a = temp;}return a;}
}

与你代码的主要区别

特性你的代码优雅版代码
资源管理手动调用scanner.close()使用try-with-resources自动关闭
空格处理split(" ")split("\\s+")(处理多个空格)
GCD 实现迭代循环递归(更简洁)
异常处理捕获输入格式错误
输出格式字符串拼接printf格式化输出
负数处理未处理Math.abs()处理负数

关键优化点解释

  1. 资源自动关闭

    java

    try (Scanner scanner = new Scanner(System.in)) {// 代码块结束时自动关闭scanner
    }
    
  2. 正则表达式处理空格

    java

    split("\\s+") // 匹配任意数量的空白字符(空格、制表符等)
    
  3. 递归 GCD

    java

    public static int gcd(int a, int b) {return b == 0 ? a : gcd(b, a % b);
    }
    
  4. 格式化输出

    java

    System.out.printf("%d %d%n", gcd, lcm); // 更清晰的输出控制
    
  5. 异常处理

    java

    catch (Exception e) {System.err.println("输入格式错误: " + e.getMessage());
    }
    

总结

你的代码已经正确实现了核心功能,而优雅版代码主要在以下方面进行了提升:

  1. 代码简洁性:递归、正则表达式减少了代码量
  2. 健壮性:异常处理和资源管理更完善
  3. 可读性printf和方法设计更符合 Java 风格

在实际开发中,建议优先考虑代码的健壮性和可维护性,而不是一味追求简洁。你的实现已经很好,这些优化点可以作为未来的参考!

谢谢ai的点评,/(ㄒoㄒ)/~~,感觉就是这样才能进步啊!!!加油!今天先写到这里啦~明天继续加油~!~!~!~!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/79564.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/79564.shtml
英文地址,请注明出处:http://en.pswp.cn/web/79564.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI 在模仿历史语言方面面临挑战:大型语言模型在生成历史风格文本时的困境与研究进展

概述 在当今数字化时代&#xff0c;人工智能&#xff08;AI&#xff09;技术在诸多领域展现出了强大的能力&#xff0c;但在处理历史语言这一特定任务时&#xff0c;却遭遇了不小的挑战。美国和加拿大的研究人员通过合作发现&#xff0c;像 ChatGPT 这样的大型语言模型&#x…

基于 Spring Boot 瑞吉外卖系统开发(十二)

基于 Spring Boot 瑞吉外卖系统开发&#xff08;十二&#xff09; 菜品删除 单击“批量删除”和“删除”时&#xff0c;会携带需要删除的菜品的id以delete请求方式向“/dish”发送请求。 URLhttp://127.0.0.1:8080/dish调用方法DELETE参数ids DishController添加删除方法 …

Day22打卡-复习

复习日 仔细回顾一下之前21天的内容&#xff0c;没跟上进度的同学补一下进度。 作业&#xff1a; 自行学习参考如何使用kaggle平台&#xff0c;写下使用注意点&#xff0c;并对下述比赛提交代码 泰坦尼克号人员生还预测https://www.kaggle.com/competitions/titanic/overview K…

L48.【LeetCode题解】904. 水果成篮

目录 1.题目 2.分析 方法1:暴力枚举 方法2:暴力解法的优化:滑动窗口 代码 方法3:优化方法2:使用数组充当哈希表 方法4:四个变量分别充当篮子和篮子中水果的个数(最快!!!) 代码 容易忽略的点 1.题目 https://leetcode.cn/problems/fruit-into-baskets/ 你正在探访一家农…

Leetcode-BFS问题

LeetCode-BFS问题 1.Floodfill问题 1.图像渲染问题 [https://leetcode.cn/problems/flood-fill/description/](https://leetcode.cn/problems/flood-fill/description/) class Solution {public int[][] floodFill(int[][] image, int sr, int sc, int color) {//可以借助另一…

Typora+PicGo+Gitee图床配置教程 自动图片上传

配置步骤 #mermaid-svg-aPUbWs43XR5Rh7vf {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-aPUbWs43XR5Rh7vf .error-icon{fill:#552222;}#mermaid-svg-aPUbWs43XR5Rh7vf .error-text{fill:#552222;stroke:#552222;}#…

养生:开启健康生活的全新篇章

养生是一场关乎生活品质与身心健康的持续修行&#xff0c;从饮食调养到运动锻炼&#xff0c;从睡眠管理到心态塑造&#xff0c;每个环节都对健康有着深远影响。以下为你提供全面且实用的养生指南。 饮食养生&#xff1a;科学膳食&#xff0c;滋养生命 合理的饮食是养生的根基…

Python | 赤道频散关系图

写在前面 写开题报告&#xff0c; 想用个图发现截出来全是糊的。索性自己画了&#xff0c;主要实现的Matsuno&#xff08;1966&#xff09;的赤道波动频散关系图。但是&#xff0c;实在是没有审美&#xff0c;其他文献里都是黑色&#xff0c;这里非要用个紫色&#xff0c;因为…

Nexus 私有仓库 + Nginx 反向代理部署文档

1. 使用 Podman 部署 Nexus 3 podman run --name nexus -d \-p 8081:8081 \-v /data:/nexus-data \-v /etc/localtime:/etc/localtime \-e TZ"Asia/Shanghai" \-e INSTALL4J_ADD_VM_PARAMS"-Xms10240m -Xmx10240m -XX:MaxDirectMemorySize4096m" \docker.…

一.Gitee基本操作

一.初始化 1.git init初始化仓库 git init 用于在当前目录下初始化一个本地 Git 仓库&#xff0c;让这个目录开始被 Git 跟踪和管理。 生成 .git 元数据目录&#xff0c;从而可以开始进行提交、回退、分支管理等操作。 2.git config user.name/user.email配置本地仓库 # 设置…

力扣210(拓扑排序)

210. 课程表 II - 力扣&#xff08;LeetCode&#xff09; 这是一道拓扑排序的模板题。简单来说&#xff0c;给出一个有向图&#xff0c;把这个有向图转成线性的排序就叫拓扑排序。如果有向图中有环就没有办法进行拓扑排序了。因此&#xff0c;拓扑排序也是图论中判断有向无环图…

华为ensp实现跨vlan通信

要在网络拓扑中实现主机192.168.1.1、192.168.1.2和192.168.2.1之间的互相通信&#xff0c;需要正确配置交换机&#xff08;S5700&#xff09;和路由器&#xff08;AR3260&#xff09;&#xff0c;以确保不同网段之间的通信&#xff08;即VLAN间路由&#xff09;。 网络拓扑分析…

热部署与双亲委派

热部署初探与双亲委派机制 一、热部署初探 ​ 热部署就是在不重启服务的情况下&#xff0c;无需重新启动整个应用&#xff0c;就能对代码、配置等进行更新并使新的更改在服务中生效。以下代码可以打破双亲委派机制&#xff0c;利用类加载器的隔离实现热部署。可分为以下三步进…

AWS SNS:解锁高并发消息通知与系统集成的云端利器

导语 在分布式系统架构中&#xff0c;如何实现高效、可靠的消息通知与跨服务通信&#xff1f;AWS Simple Notification Service&#xff08;SNS&#xff09;作为全托管的发布/订阅&#xff08;Pub/Sub&#xff09;服务&#xff0c;正在成为企业构建弹性系统的核心组件。本文深度…

驱动开发硬核特训 · Day 30(下篇): 深入解析 lm48100q I2C 音频编解码器驱动模型(基于 i.MX8MP)

作者&#xff1a;嵌入式Jerry 视频教程请关注 B 站&#xff1a;“嵌入式Jerry” 一、背景与目标 在本篇中&#xff0c;我们围绕 TI 的 lm48100q 音频编解码器 展开&#xff0c;深入讲解其作为 I2C 外设如何集成至 Linux 内核音频子系统&#xff08;ASoC&#xff09;&#xff0…

idea写spark程序

步骤 1&#xff1a;创建 Maven 项目 打开 IntelliJ IDEA&#xff0c;选择 File > New > Project。选择 Maven&#xff0c;勾选 Create from archetype&#xff0c;选择 org.apache.maven.archetypes:maven-archetype-quickstart。填写 GroupId&#xff08;如 com.exampl…

【C语言练习】032. 编写带参数的函数

032. 编写带参数的函数 032. 编写带参数的函数1. 定义带参数的函数示例1:定义一个带参数的函数输出结果2. 传递多个参数示例2:定义一个带多个参数的函数输出结果3. 传递数组作为参数示例3:定义一个带数组参数的函数输出结果4. 传递结构体作为参数示例4:定义一个带结构体参数…

Java虚拟机的基本结构

jvm它包含以下部分 第一个&#xff1a;类加载系统 类加载子系统&#xff0c;负责类的加载。类加载器有三种类型&#xff1a;引导类加载器、扩展类加载器、应用程序类加载器。 第二个&#xff1a;运行时数据区 包含了程序计数器、Java虚拟机栈、本地方法栈、堆 、方法区。 程…

uniapp引入七鱼客服微信小程序SDK

小程序引入七鱼sdk 1.微信公众平台引入2.代码引入3.在pagesQiyu.vue初始化企业appKey4.跳转打开七鱼客服 1.微信公众平台引入 账号设置->第三方设置->添加插件->搜索 QIYUSDK ->添加 2.代码引入 在分包中引入插件 "subPackages": [{"root":…

手撕算法(定制整理版2)

最长无重复子字符串 class Solution(object):def lengthOfLongestSubstring(self, s):""":type s: str:rtype: int"""if not s:return 0max_len 0tp []for a in s:while a in tp:del tp[0]tp.append(a)if len(tp) > max_len:max_len len(…