总结:
2016:求生日蜡烛。 暴力循环
2017:等边三角形排法。 全排列(递归)/暴力循环
2018:圆内完整小方格数。 暴力循环
2019:不同子串。 暴力循环、字符串
2020-1:某两天间分钟。 函数的掌握
2020-2:大型矩阵中找2020。 暴力循环
2021:数字卡片。 暴力循环、数字分割
2022:“山”型数字。 暴力查找
综上:第二题普遍数据量特别大,直接排除学生口算或能一眼看出来的可能。
如果第一题可以借助工具或一眼看出答案,那么第二题就得通过简单编程实现了。
通过分析近些年题型,对于第二题只要能看懂题目、知道总体解题思路、会简单循环和判断(即暴力算法)就能做出来。
主要考察:1、循环,而且很可能是暴力循环(数据量很大)(如:2016年、2017年、2018年、2020年-2、2021年、2022年)
2、字符串各种函数功能(字符和数字间的转换函数)(如:2019年、2020年-1、2020年-2、2022年)
3、数学思维(全排列、求圆半径公式、等边三角形三边相等)(如:2016年、2017年、2018年、2021年、2022年)
4、找规律(如:2016年、2017年)
接下来列出2016年-2022年间第2题的详细讲解:
2016年
某君从某年开始每年都举办一次生日party,并且每次都要吹熄与年龄相同根数的蜡烛。现在算起来,他一共吹熄了236根蜡烛。请问,他从多少岁开始过生日party的?
请填写他开始过生日party的年龄数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
public static void main(String[] args){
int x;//蜡烛数
for(int i=1;i<50;i++){//从1岁开始计算,50是一个大概上限
x=i;
for(int j=i+1;j<50;j++){//遍历之后每年
x+=j;//i到j年间(包括第j年)蜡烛总数
if(x>236)break;
if(x==236){//找到
System.out.println(i);
break;
}
}
}
}
答案:26
思路:(暴力算法)从第一岁开始,一年一年地计算,直到遍历到符合题目地年龄。
2017年
A,2,3,4,5,6,7,8,9 共9张纸牌排成一个正三角形(A按1计算)。要求每个边的和相等。下图就是一种排法。这样的排法可能会有很多。如果考虑旋转、镜像后相同的算同一种,一共有多少种不同的排法呢?
A
9 6
4 8
3 7 5 2
请你计算并提交该数字。
注意:需要提交的是一个整数,不要提交任何多余内容。
方法一:暴力算法。
public static void main(String[] args){
int count=0;
for(int a=1; a<=9;a++) {
for(int b=1; b<=9; b++) {
for(int c=1;c<=9;c++) {
for(int d=1;d<=9;d++) {
for(int e=1;e<=9;e++) {
for(int f=1;f<=9;f++) {
for(int g=1; g<=9;g++) {
for(int h=1;h<=9;h++) {
for(int i=1;i<=9;i++) {
if(a!=b&&a!=c&&a!=d&&a!=e&&a!=f&&a!=g&&a!=h&&a!=i&&
b!=c&&b!=d&&b!=e&&b!=f&&b!=g&&b!=h&&b!=i&&
c!=d&&c!=e&&c!=f&&c!=g&&c!=h&&c!=i&&
d!=e&&d!=f&&d!=g&&d!=h&&d!=i&&
e!=f&&e!=g&&e!=h&&e!=i&&
f!=g&&f!=h&&f!=i&&
g!=h&&g!=i&&
h!=i) {
if((a+b+d+f)==(a+c+e+i)&&(a+c+e+i)==(f+g+h+i)) count++;}}}}}}}}}}
System.out.println(count/6);
}
方法二:全排列(递归)(不太好理解)
public static void main(String[] args) {
dfs(0);
System.out.println(ans/6);//
}
static int[] a = new int[] {1,2,3,4,5,6,7,8,9};
static int ans = 0;
static void dfs(int m) {
if(m>=9) {
if(a[0]+a[1]+a[3]+a[5]==a[0]+a[2]+a[4]+a[8]&&a[0]+a[2]+a[4]+a[8]==a[5]+a[6]+a[7]+a[8])
ans++;
return;
}
for(int i=m;i<9;i++) {
swap(i,m);
dfs(m+1);
swap(i,m);
}
}
static void swap(int i,int j) {
int t = a[i];
a[i] =a[j];
a[j] = t;
}
}
答案:144
思路:先固定一位数,其余数全排列。循环直到每一位数都在每个位置上被固定过。
比如对数组a={1,2,3,4},其全排列为:1234、1243、1324、1342、1423、1432
2134、2143、2314、2341、2431、2413..........
全排列讲解请移步:全排列
总上对递归分析如下:(图点开放大看)
由于每个位置固定情况下通过旋转和镜像有6种情况相同,所以对计算结果除6即为答案。
2018年
如图所示,在二维平面上有无数个1x1的小方格。我们以某个小方格的一个顶点为圆心画一个半径为1000的圆。你能计算出这个圆里有多少个完整的小方格吗?
public static void main(String[] args){
int sum=0;
for(int i=1;i<1000;i++){
for(int j=1;j<1000;j++){
if(i*i+j*j<=1000*1000)sum++;
}
}
System.out.println(sum*4);
答案:3137548
思路:对1/4圆进行分析。由a^2+b^2=r^2公式进行计算,求得1/4圆内完整的小方格。结果再乘4就是整个圆内完整的小方格数。
2019年
一个字符串的非空子串是指字符串中长度至少为 1 的连续的一段字符组成的串。例如,字符串aaab 有非空子串a, b, aa, ab, aaa, aab, aaab,一共 7 个。注意在计算时,只算本质不同的串的个数。
请问,字符串0100110001010001 有多少个不同的非空子串?
public static void main(String[] args){
String str="0100110001010001";
HashSet<Object> set = new HashSet<>();
for(int i=0;i<str.length();i++){
for(int j=i;j<str.length();j++){
String s=str.substring(i,j+1);//将字符串从i位置分割,并保存i之后字符串在set中
set.add(s);
}
}
System.out.println(set.size());
}
答案:100
思路:使用哈希substring方法直接将字符串进行分割并保存。最后通过size求其数量。
2020年-1
2020 年 7 月 1 日是中国共产党成立 99 周年纪念日。中国共产党成立于 1921 年 7 月 23 日。
请问从 1921 年 7 月 23 日中午 12 时到 2020 年 7 月 1 日中午 12 时一共包含多少分钟?
public static void main(String[] args) throws ParseException {
DateFormat format=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//定义时间格式
Date start=format.parse("1921-7-23 12:00:00");//将文本时间转为Date时间型
Date end=format.parse("2020-7-1 12:00:00");
long x= ((end.getTime()-start.getTime())/1000/60);//除1000表示以秒为单位,除60表示以分为单位
System.out.println(x);
}
答案:52038720
思路:利用DateFormat对象将时间文本转为时间格式并进行计算。
注意:y:年、M:月、m:分种、d:天、H:24小时制、h:12小时制、s:秒。
2020年-2
小蓝有一个数字矩阵,里面只包含数字 0 和 2。小蓝很喜欢 2020,他想找到这个数字矩阵中有多少个 2020 。小蓝只关注三种构成 2020 的方式:同一行里面连续四个字符从左到右构成 2020。同一列里面连续四个字符从上到下构成 2020。在一条从左上到右下的斜线上连续四个字符,从左上到右下构成 2020。例如,对于下面的矩阵:
220000
000000
002202
000000
000022
002020
一共有 5 个 2020。其中 1 个是在同一行里的,1 个是在同一列里的,3 个是斜线上的。小蓝的矩阵比上面的矩阵要大,由于太大了,他只好将这个矩阵放在了一个文件里面,在试题目录下有一个文件 2020.txt,里面给出了小蓝的矩阵。请帮助小蓝确定在他的矩阵中有多少个 2020。
(以例子矩阵给出代码)
public static void main(String[] args){
int m=6;
int n=6;
int sum=0;
char[][] ch=new char[m][n];
Scanner input=new Scanner(System.in);
for(int i=0;i<m;i++){
ch[i]=input.nextLine().toCharArray();
}
//横向找
for(int i=0;i<m;i++){
for(int j=0;j<n-3;j++){
if(ch[i][j]=='2' && ch[i][j+1]=='0' && ch[i][j+2]=='2' && ch[i][j+3]=='0')
sum++;
}
}
//竖向找
for(int i=0;i<m-3;i++){
for(int j=0;j<n;j++){
if(ch[i][j]=='2' && ch[i+1][j]=='0' && ch[i+2][j]=='2' && ch[i+3][j]=='0')
sum++;
}
}
//斜向找
for(int i=0;i<m-3;i++){
for(int j=0;j<n-3;j++){
if(ch[i][j]=='2'&&ch[i+1][j+1]=='0'&&ch[i+2][j+2]=='2'&&ch[i+3][j+3]=='0')
sum++;
}
}
System.out.println(sum);
}
答案:5
思路:分别从三个放向进行查找(横向、竖向、斜向),如果满需要求就计数。
2021年
小蓝有很多数字卡片,每张卡片上都是数字0 到9。小蓝准备用这些卡片来拼一些数,他想从1 开始拼出正整数,每拼一个,就保存起来,卡片就不能用来拼其它数了。小蓝想知道自己能从1 拼到多少。
例如,当小蓝有30 张卡片,其中0 到9 各3 张,则小蓝可以拼出1 到10,但是拼11 时卡片1 已经只有一张了,不够拼出11。现在小蓝手里有0 到9 的卡片各2021 张,共20210 张,请问小蓝可以从1拼到多少?提示:建议使用计算机编程解决问题。
public static void main(String[] args){
int[] array=new int[10];//数组array每个值表示0-9数字的个数
Arrays.fill(array,2021);//将数组array所有值设为2021
for(int i=1;;i++){
int temp=i;
while (temp>0){//循环数字的每一位寻找数字卡片
int r=temp%10;//取数的最后一位
if(array[r]>0)//如果该数字卡片还有则使用一张
array[r]--;
else {//该数字卡片用完了,表示达到最大拼出的数字,退出程序
System.out.println(i-1);
return;
}
temp/=10;//去掉最后一位循环找剩下数字的卡片
}
}
}
答案:3181
思路:数组a中存放1~9每张卡片的个数,从1开始进行拼图,用完一个数字该数组-1,直到数组内任意一个数字卡片个数为0。
2022年
这天小明正在学数数。他突然发现有些正整数的形状像一座“山”,比如 123565321 、 145541 ,它们左右对称(回文)且数位上的数字先单调不减,后单调不增。小明数了很久也没有数完,他想让你告诉他在区间[2022,2022222022]中有多少个数的形状像一座“山”。
public static void main(String[] args) {
int count = 0;
for (int i = 2022; i <= 2022222022; i++) {//循环区间内所有数字
if(isHuiWen(i)&&isDiZenDiJian(i))//满足条件则计数
count++;
}
System.out.println(count);
}
public static boolean isHuiWen(int sum){//判断回文
StringBuilder str=new StringBuilder(sum+"");
return (str.reverse().toString()).equals(sum+"");//正序与反序对比是否相等
}
public static boolean isDiZenDiJian(int sum){//判断递增递减
String s=sum+"";
int mid=s.length()%2==0?s.length()/2:s.length()/2+1;//求数字中间下标
for(int i=0;i<mid-1;i++){//从头到中间判断是否满足递增要求
if(s.charAt(i)>s.charAt(i+1))
return false;
}
return true;
}
答案:3138
思路:对区间内的每个数字进行回文和递增判断,符合要求则计数。