链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
题目一
请统计某个给定范围[L, R]的所有整数中,数字2出现的次数。
比如给定范围[2, 22],数字2在数2中出现了1次,在数12中出现1次,在数20中出现1次,在数21中出现1次,在数22中出现2次,所以数字2在该范围内一共出现了6次。
输入描述:
输入共1行,为两个正整数L和R,之间用一个空格隔开。
输出描述:
输出共1行,表示数字2出现的次数。
示例1
输入
2 22
输出
6
示例2
输入
2 100
输出
20
Java代码展示:
import java.util.Scanner;public class Main{public static void main(String[] args){int a=0,b=0,num=0;Scanner in =new Scanner(System.in);//这个是循环读取a =in.nextInt();b =in.nextInt();for(int i=a;i<=b;i++){int temp =i;while(temp!=0){int j=temp%10;if(j==2){num++;}temp/=10;}}System.out.println(num);}
}
注意:
在 Java 中,变量 i
是 for
循环的迭代变量,它在循环的每次迭代中都会被更新。如果在 while
循环中直接使用 i
而不创建 temp
变量,会出现以下问题:
当我们在 while
循环中修改 i
的值(通过 temp /= 10
),这会影响 for
循环的迭代过程。因为 i
不仅是 while
循环的控制变量,也是 for
循环的迭代变量,修改 i
会导致 for
循环的迭代逻辑出现错误。
例如,假设 i
的初始值是 123
,在 while
循环中你将 i
不断除以 10
来检查其每一位数字是否为 2
。第一次 while
循环结束后,i
的值就变成了 12
,而不是 for
循环期望的下一个迭代值 124
。这会导致 for
循环的迭代顺序被破坏,最终结果错误。
为了避免这种情况,我们应该引入了 temp
变量,将 i
的值复制给 temp
,然后在 while
循环中对 temp
进行操作,这样就不会影响 for
循环的迭代过程。
题目二
题目描述:B-日历中的数字_牛客竞赛语法入门班函数与递归习题
只通过了测试样例的代码。。。
// 日中包含的 月中包含的 年中包含的// 数字x在这个月的日期里出现了多少次。//闰年
import java.util.Scanner;public class Main{public static void main(String[] args){Scanner in =new Scanner(System.in);while(in.hasNextInt()){int count=0;int q=0;int year =in.nextInt();int month =in.nextInt();int num =in.nextInt();while(year!=0){if(year%10 ==num){q++;}year/=10;}int[] date={31,28,31,30,31,30,31,31,30,31,30,31};count+=q*date[month-1];int temp1=month;while(temp1!=0){if(temp1%10==num){if(temp1==2){count+=date[month-1];//判断闰年代码if((year % 4 == 0 && year % 100!= 0) || year % 400 == 0){count+=1;}}else{count+=date[month-1];}}temp1/=10;}for(int i=1;i<=date[month-1];i++){int temp=i;while(temp!=0){if(temp%10==num){count++;}temp/=10;}}if(num==0){count+=9;if(month<10){count+=date[month-1];}}System.out.println(count);}}
}
正确代码展示:
import java.util.Scanner;public class Main {public static void main(String[] args) {// 创建一个 Scanner 对象,用于从标准输入读取数据Scanner sc = new Scanner(System.in);// 定义一个数组 arr 存储每个月的天数,2 月初始化为 28 天int[] arr = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};// 进入一个循环,只要输入流还有数据,就会一直执行while (sc.hasNext()) {// 创建一个 StringBuilder 对象,用于存储日期字符串StringBuilder sb = new StringBuilder();// 从输入读取年份 yint y = sc.nextInt();// 从输入读取月份 mint m = sc.nextInt();// 从输入读取一个字符 xchar x = sc.next().charAt(0);// 判断是否为闰年,如果是闰年将 2 月的天数修改为 29 天,否则为 28 天if (y % 400 == 0 || (y % 4 == 0 && y % 100!= 0)) {arr[1] = 29;} else {arr[1] = 28;}// 循环遍历该月的每一天for (int i = 1; i <= arr[m - 1]; i++) {// 使用 String.format 方法将年份、月份和日期组合成一个字符串,格式为 yyyymmdd// %04d 表示年份为 4 位数字,不足 4 位在前面补 0// %02d 表示月份和日期为 2 位数字,不足 2 位在前面补 0String date = String.format("%04d%02d%02d", y, m, i);// 将生成的日期字符串添加到 StringBuilder 中sb.append(date);}// 计数器,用于统计字符 x 出现的次数int count = 0;// 遍历 StringBuilder 中的每个字符for (int i = 0; i < sb.length(); i++) {// 如果字符等于输入的字符 x,计数器加 1if (sb.charAt(i) == x) {count++;}}// 输出字符 x 在所有日期字符串中出现的次数System.out.println(count);}}
}
代码实现逻辑分析:
-
导入包和类的定义:
-
import java.util.Scanner;
:导入Scanner
类,用于从标准输入读取数据。 -
public class Main
:定义一个名为Main
的公共类。 -
public static void main(String[] args)
:程序的入口点。
-
-
变量和对象的初始化:
-
Scanner sc = new Scanner(System.in);
:创建一个Scanner
对象,用于读取用户输入。 -
int[] arr = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
:存储每个月的天数,初始时 2 月为 28 天。
-
-
输入处理和闰年判断:
-
while (sc.hasNext())
:只要输入流还有数据,就会执行以下操作。 -
StringBuilder sb = new StringBuilder();
:创建一个StringBuilder
对象,用于存储组合的日期字符串。 -
int y = sc.nextInt();
:从输入读取年份。 -
int m = sc.nextInt();
:从输入读取月份。 -
char x = sc.next().charAt(0);
:从输入读取一个字符。 -
对输入的年份
y
进行闰年判断,如果是闰年(能被 400 整除或能被 4 整除但不能被 100 整除),将arr[1]
(2 月的天数)设置为 29 天,否则为 28 天。
-
-
日期字符串的生成和存储:
-
for (int i = 1; i <= arr[m - 1]; i++)
:遍历该月的每一天。 -
String date = String.format("%04d%02d%02d", y, m, i);
:将年份、月份和日期格式化为yyyymmdd
的字符串。 -
sb.append(date);
:将生成的日期字符串添加到StringBuilder
中。
-
-
字符计数:
-
int count = 0;
:初始化一个计数器,用于统计字符x
的出现次数。 -
for (int i = 0; i < sb.length(); i++)
:遍历StringBuilder
中的字符。 -
if (sb.charAt(i) == x)
:如果字符等于输入的字符x
,计数器加 1。
-
-
结果输出:
-
System.out.println(count);
:输出字符x
在存储的日期字符串中出现的次数。
-
使用说明:
-
运行程序后,程序会不断等待用户输入。
-
每次输入的格式应该是:
年份 月份 字符
,例如2024 2 a
。 -
程序会将输入的年份、月份和该月的日期按照
yyyymmdd
的格式组合成一个字符串,存储在StringBuilder
中。 -
程序会根据输入的年份判断是否为闰年,并更新 2 月的天数。
-
最后程序会统计输入的字符在存储的日期字符串中出现的次数并输出结果。
这个程序的主要目的是统计用户输入的字符在该年该月的日期字符串中出现的次数。例如,输入 2024 2 a
,程序会将 2024 年 2 月的日期 20240201
到 20240229
组合成一个字符串,然后统计字符 a
在这个字符串中出现的次数。
错误原因分析 :
就是感觉自己写代码并没有利用到计算机的精髓,甚至认为计算机实现比大脑自己想还要复杂,就感觉怪怪的,自己写一堆代码,麻烦的判断是不是闰年,如果年有这个数字怎么办?月有这个数字怎么办?就感觉计算机并没有帮到任何忙,只是把我的人脑思考的思路实现了。
知识点对应函数的学习:
-
sc.next().charAt(0)
: -
sc.next()
用于读取输入的下一个字符串,而charAt(0)
是String
类的方法,用于获取该字符串的第一个字符。例如,char x = sc.next().charAt(0);
这一行先读取一个字符串,然后取其第一个字符存储在x
中。 -
String.format()
: -
这是
String
类的一个静态方法,用于格式化字符串。在代码中String date = String.format("%04d%02d%02d", y, m, i);
它将y
(年份)、m
(月份)和i
(日期)按照%04d%02d%02d
的格式组合成一个新的字符串。%04d
表示将整数格式化为 4 位数字,不足 4 位在前面补零,%02d
表示将整数格式化为 2 位数字,不足 2 位在前面补零 -
StringBuilder用法
一、创建 StringBuilder 对象:
StringBuilder sb = new StringBuilder();
上述代码创建了一个空的 StringBuilder
对象。StringBuilder
类提供了一种可变的字符串序列,允许对字符串进行动态操作,与 String
类不同,String
对象是不可变的,一旦创建,其内容不能修改,而 StringBuilder
可以在原有的基础上添加、插入、删除和替换字符。
二、添加内容到 StringBuilder:
1、append()
方法:
sb.append("Hello");
sb.append(" ");
sb.append("World");
这个方法可以将各种数据类型(如 String
、char
、int
、double
等)添加到 StringBuilder
对象的末尾。在我的代码中:
for (int i = 1; i <= arr[m - 1]; i++) {String date = String.format("%04d%02d%02d", y, m, i);sb.append(date);
}
通过 append
方法将格式化后的日期字符串添加到 sb
中,最终形成一个包含该月所有日期的长字符串。
三、插入内容到 StringBuilder:
1、insert()
方法:
sb.insert(5, " there");
此方法可以在 StringBuilder
的指定位置插入内容。例如,上述代码将在索引为 5 的位置插入 " there"
,如果 sb
原本存储 "Hello World"
,操作后会变成 "Hello there World"
。
四、删除内容:
1、delete()
方法:
sb.delete(5, 11);
这个方法可以删除 StringBuilder
中从起始索引到结束索引(不包括结束索引)的字符。例如,在上述插入操作后,使用 delete
方法会将 " there"
删除,sb
会变回 "Hello World"
。
2、deleteCharAt()
方法:
sb.deleteCharAt(5);
该方法会删除 StringBuilder
中指定索引处的字符。
五、替换内容:
1、replace()
方法:
sb.replace(0, 5, "Hi");
此方法将从起始索引到结束索引(不包括结束索引)的内容替换为新的字符串。上述代码将把 "Hello"
替换为 "Hi"
,如果 sb
存储 "Hello World"
,操作后会变成 "Hi World"
。
六、反转 StringBuilder 内容:
reverse()
方法:
sb.reverse();
该方法会将 StringBuilder
中的字符序列进行反转。例如,如果 sb
存储 "Hello World"
,操作后会变成 "dlroW olleH"
。
七、转换为 String:
toString()
方法:
String result = sb.toString();
这个方法将 StringBuilder
的内容转换为 String
类型,在需要将 StringBuilder
的内容作为字符串使用时,通常使用这个方法。
八、其他有用的方法:
1、length()
方法:
int len = sb.length();
该方法返回 StringBuilder
中字符序列的长度。
2、charAt()
方法:
char c = sb.charAt(0);
此方法返回 StringBuilder
中指定索引处的字符。
在原代码中,使用 StringBuilder
的目的是将一个月的所有日期按照 yyyymmdd
的格式拼接成一个长字符串,以便后续统计某个字符的出现次数。通过循环将日期添加到 StringBuilder
中,避免了多次字符串拼接造成的性能开销(因为每次使用 String
拼接都会创建新的 String
对象,而 StringBuilder
只在原对象上操作)。
import java.util.Scanner;public class StringBuilderExample {public static void main(String[] args) {StringBuilder sb = new StringBuilder();// 添加字符串sb.append("I");sb.append(" love");sb.append(" Java");// 插入字符串sb.insert(2, " really ");// 删除字符串sb.delete(2, 9);// 替换字符串sb.replace(0, 1, "We");// 反转字符串sb.reverse();// 输出最终结果System.out.println(sb.toString());}
}
在上述示例中,我们展示了 StringBuilder
的多种操作。首先添加 "I love Java"
,然后在索引 2 处插入 " really "
,再删除 " really "
,接着将 "I"
替换为 "We"
,最后将整个字符串反转。
使用 StringBuilder
可以提高字符串操作的效率,特别是在需要频繁修改字符串内容的情况下,避免了 String
的不可变特性带来的性能问题。同时,StringBuilder
提供了丰富的方法,可以方便地对字符串进行各种修改和操作。