回文日期 (蓝桥云) JAVA

文章讲述了作者在参加蓝桥杯编程竞赛时遇到的回文日期问题,以及解决此类问题的心得体会。作者强调了细心审题、编写可应对多种情况的代码以及处理代码间关系的重要性,通过实例解析了如何检查和优化代码,以提高正确率和适应OI赛制。
摘要由CSDN通过智能技术生成

题目描述:

2020 年春节期间,有一个特殊的日期引起了大家的注意:2020 年 2 月 2 日。因为如果将这个日期按 “yyyymmdd”
的格式写成一个 8 位数是 20200202,恰好是一个回文数。我们称这样的日期是回文日期。

有人表示 20200202 是 “千年一遇” 的特殊日子。对此小明很不认同,因为不到 2 年之后就是下一个回文日期:20211202 即
2021 年 12 月 2 日。

也有人表示 20200202 并不仅仅是一个回文日期,还是一个 ABABBABA 型的回文日期。对此小明也不认同,因为大约 100
年后就能遇到下一个 ABABBABA 型的回文日期:21211212 即 2121 年 12 月 12 日。算不上 “千年一遇”,顶多算
“千年两遇”。

给定一个 8 位数的日期,请你计算该日期之后下一个回文日期和下一个 ABABBABA 型的回文日期各是哪一天。

输入描述:

输入包含一个八位整数 N,表示日期。

对于所有评测用例,
10000101 ≤ 89991231
N 是一个合法日期的 8 位数表示。

输出描述:

输出两行,每行 1 个八位数。第一行表示下一个回文日期,第二行表示下一个 ABABBABA 型的回文日期。

输入输出样例:

输入

20200202

输出

20211202
21211212


统领:

第一次参加蓝桥杯,所以今天才知道蓝桥杯采用oi机制,即提交后没有任何反馈,这给我的冲击很大,因为我平常写完代码,第一时间是去平台测试,根据平台反馈,找错误原因,而蓝桥杯的赛制,直接让我的这个习惯成为了最大破绽。失去了通过平台找错因的手段,让我备受打击,抱着从头再来的想法。我在蓝桥云找了一道适合我水平的题目,试试一遍能得多少分。
好在这一次侥幸能够全部AC给我带来了一丝希望,以下是通过题目总结我的心得。


本题完整代码:

import java.util.*;
public class Main {
   public static  int month[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
   public static void main(String[] args) {
	   Scanner sc = new Scanner(System.in);
       int n = sc.nextInt();
       int yy = n / 10000;
       //System.out.println(yy);
       while(true) {
    	   if(check(yy)) {
    		   StringBuffer s = new StringBuffer(String.valueOf(yy));
    		   String s1 = String.valueOf(yy);
    		   s1 = s1 + s.reverse();
    		   if(Integer.parseInt(s1) > n) {
    		     System.out.println(s1);
    		     break;
    		   }
    	   }
    	   yy  = yy + 1;
       }
       int YY = n / 1000000;
       while(true) {
    	   if(check_y(YY)) {
    		   StringBuffer s2 = new StringBuffer(String.valueOf(YY * 100 + YY));
    		   String s3 = String.valueOf(YY * 100 + YY) + s2.reverse();
    		   if(Integer.parseInt(s3) > n) {
    		     System.out.print(s3);
    		     break;
    		   }
    	   }
    	   YY = YY + 1;
       }
   }
   public static boolean check_y(int m) {
	   int yy = m * 100 + m;
	   if(yy % 4 == 0 && yy % 100 != 0 || yy % 400 == 0) {
		   month[2] = 29;
	   }
	   else month[2] = 28;
	   StringBuffer s = new StringBuffer(String.valueOf(yy));
	   String s1 = "" + s.reverse();
	   int mm = Integer.parseInt(s1.substring(0, 2));
	   int dd = Integer.parseInt(s1.substring(2, 4));
	   //System.out.println(month[2]);
	   if(mm <= 0 || mm > 12) return false;
	   if(month[mm] < dd) return false;
	   return true;
   }
   public static boolean check(int n) {
	   int yy = n;
	   if(yy % 4 == 0 && yy % 100 != 0 || yy % 400 == 0) {
		   month[2] = 29;
	   }
	   StringBuffer s = new StringBuffer(String.valueOf(yy));
	   String s1 = "" + s.reverse();
	   int mm = Integer.parseInt(s1.substring(0, 2));
	   int dd = Integer.parseInt(s1.substring(2, 4));
	   //System.out.println(month[2]);
	   if(mm <= 0 || mm > 12) return false;
	   if(month[mm] < dd) return false;
	   return true;
   }
}

心得:

蓝桥杯是提交没有反馈的,所以我们得细心细心再细心,不要图快,急着把做后面的题。我导师跟我说一个大哥,去年参赛国二,卷了一年再考蓝桥杯只得了省三。问题不在于他题不会,他是所有题都做了。可想而知,他做的题可能只能通过题目给的样例,而样例又不算分数。所以为了能稳定发挥吧,我对自己的建议是:

1.反复斟酌题目要求:

如果你有一道题是会做的,程序也写出来了,那就要务必保证其能对尽可能多的测试点,题目一定要多读几遍,就拿上述题目来举例子,题目要求输出该日期之后的下一个回文日期,假若你没注意到这一点,那么当N = 20201221时,你的程序输出的可能就是20200202这个输出显然不是正确答案

2.小心谨慎步步为营,多反问:

首先我们应该问自己所有的八位回文数字串都行么?

显然回文日期的月份和天数都得合法才行,即月份应在[0, 12], 天数应该在当月的范围内

再思考到当月的天数范围,我们就意识到了,还得判断这个年是闰年还是平年,这样二月的天数范围我们就明确了

考虑到上述问题后,我们的正确率就提高了,然后就是构思去实现一个check函数判断我们的回文日期是否合法:

public static boolean check(int n) {
	   int yy = n;
	   if(yy % 4 == 0 && yy % 100 != 0 || yy % 400 == 0) {
		   month[2] = 29;
	   }
	   StringBuffer s = new StringBuffer(String.valueOf(yy));
	   String s1 = "" + s.reverse();
	   int mm = Integer.parseInt(s1.substring(0, 2));
	   int dd = Integer.parseInt(s1.substring(2, 4));
	   //System.out.println(month[2]);
	   if(mm <= 0 || mm > 12) return false;
	   if(month[mm] < dd) return false;
	   return true;
   }
}

写完check后我们不要急着走,我们应该及时检查这个check函数是否正确,多想几个样例测试一下,确保无误后再继续进行。这样如果整个代码出现问题,至少我们能排除check代码的问题,这就是步步为营。

3.调节代码之间的关系:

那本题为例输出有两个一个是回文日期,一个是ABABBABA型回文,这里就存在一个问题,如果前者输出回文日期,判断的年份刚好是闰年,我们修改了month[2] = 29而下一个这个ABABBABA型日期刚好是平年,这里就容易出问题了。

所以为了解决这个问题,实现ABABBABA型的代码就需要调整了。

 if(yy % 4 == 0 && yy % 100 != 0 || yy % 400 == 0) {
		   month[2] = 29;
	   }
	   else month[2] = 28;

如上图我添加了一个else语句,这样代码的正确率又会提高。


总结:

要想用代码去实现一道题目,我们需要把这其中很难多问题分块解决,并用代码去解决。个人亲身体会,去解决这些块问题,要比分析边界要花费的时间更多。所以如果我们写出代码后直接潦草提交,就有可能会因为其中的细节没考虑到而功亏一篑。既然我们已经投入了这么多时间去用编程解决这道题,那么为何不愿多花点时间找出可能的边界,得到更多的分数?显然有时候是我太贪心了,分不清西瓜和芝麻。

想想也是没必要抱怨,能够自己排除bug,分析可能的错因,写出优质代码,让用户有更好的体验。何尝不是一个合格程序员该具备的?😄

利用余下的时间我会继续依靠采用这种一遍过的模式做题,适应oi赛制。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值