蓝桥回文日期
Posted Mr YiRan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了蓝桥回文日期相关的知识,希望对你有一定的参考价值。
示例
输入
20200202
输出
20211202
21211212
在java中有一个类是LocalDate
LocalDate 是 Java8中新增的日期类,采用了系统的默认时区。可以方便的处理 日期对象 的 年、月、日 信息。有这个类在解决日期类问题比较方便。
下面常用的几个常用API
1.创建日期对象
获取当前日期对象
LocalDate.now() : 返回默认时区下的、系统始终下的 当前日期
2.获取日期对象的 年、月、日 信息
getYear() : 获取年分信息
getMonth() : 获取月份信息(枚举类型)
getMonthValue() : 获取月份的数字(数值类型)
getDayOfMonth() : 获取日期信息
getDayOfWeek() : 获取星期几 (枚举类型)
getDayOfYear() : 获取这一年的第几天
3.指定 日期对象的属性
withYear(int) : 设置年
withMonth(int) : 设置月
withDayOfMonth(int) : 设置日
withDayOfYear(int) : 设置这一年的第几天
with(TemporalAdjuster) : 时间调整器,更方便的调整
4.加上 或者 减去 年、月、日、周
plusYears(long) : 加几年
plusMonths(long) : 加几个月
plusDays(long) : 加几天
plusWeeks(long) : 加几个星期
minusYears(long) : 减几年
minusMonths(long) : 减几个月
minusDays(long) : 减几天
minusWeeks(long) : 减几个星期
import java.time.LocalDate;
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改
public class Main
public static void main(String[] args)
Scanner scanner=new Scanner(System.in);
String N = scanner.next();
//System.out.println(N);
int year=Integer.parseInt(N.substring(0,4));
int month=Integer.parseInt(N.substring(4,6));
int day = Integer.parseInt(N.substring(6, 8));
LocalDate date = LocalDate.now();//通过LocalDate这个类实现日期操作
//修改当前年月日
date=date.withYear(year);
date=date.withMonth(month);
date=date.withDayOfMonth(day);
//2020-02-02
//System.out.println(date);
//分割成20200202
//System.out.println(s);
String a="";//第一个回文日期
String b="";//第二个ABABBABA型回文日期
boolean isFind=false;
while(true)
//一直往后找
date=date.plusDays(1);
String s= date.toString().replace("-","");
if(isHuiWen(s))
//说明是回文数
if(!isFind)
a=s;
isFind=true;
if(isABABBABA(s))
//说明是ABABBABA类型的
b=s;
break;
System.out.println(a);
System.out.println(b);
scanner.close();
private static boolean isABABBABA(String s)
//判断ABABBABA
if(s.charAt(0)==s.charAt(7)&&s.charAt(1)==s.charAt(6)&&s.charAt(2)==s.charAt(5)
&&s.charAt(3)==s.charAt(4)&&s.charAt(0)==s.charAt(2)&&s.charAt(1)==s.charAt(3)
)
return true;
return false;
private static boolean isHuiWen(String s)
int mid=s.length()/2;
int r=s.length()-1;
// System.out.println("mid"+mid);
// System.out.println("r"+r);
// System.out.println("进来isHuiWen"+s);
for(int i=0;i<mid;i++)
// System.out.println("s.charAt(i)"+s.charAt(i));
// System.out.println("s.charAt(r)"+s.charAt(r));
if(s.charAt(i)!=s.charAt(r))
return false;
r--;
return true;
不使用LocalDate类的另一种方法
1.首先要满足回文的形式,即ABCDDCBA,对于回文的判断用数组会方便许多。
2.ABABBABA型:此处也可以使用数组判断是否是回文型。
3.要满足日期的格式。
暴力求解思路:预先存储好各个月份的天数。需要三个判断方法:
a.判断是否是闰年,如果是,则将存储的二月份的天数改为29
b.判断是否是回文型
c.判断是否是ABAB型
通过三重for循环来寻找下一次回文日期。巧妙运用for循环的执行顺序就可以实现从当前日期往后开始寻找。先增加天数,天数满了增加月份,月份也满了增加年份。要注意增加月份和年份时对应地要初始化天数和月份。通过两个Boolean值来判断是否找到我们的目标日期,当两个Boolean值都为true时说明都找到了我们的目标日期,可以退出循环了。
import java.util.*;
class Main
static boolean IsRun(int y)
if(y%400==0||(y%4==0&&y%100!=0)) return true;
return false;
static boolean ABBA(String Str)//判断回文日期
char []str=Str.toCharArray();
if(str[0]==str[7]&&str[1]==str[6]&&str[2]==str[5]&&str[3]==str[4]) return true;
return false;
static boolean ABAB(String Str) //判断ABBA型
char []str=Str.toCharArray();
if(str[0]==str[2]&&str[2]==str[5]&&str[5]==str[7]&&str[1]==str[3]&&str[3]==str[4]&&str[4]==str[6]&&str[0]!=str[1])
return true;
return false;
public static void main(String args[])
int monthes[]=0,31,28,31,30,31,30,31,31,30,31,30,31;
Scanner in=new Scanner(System.in);
String time=in.next();
Integer tt=Integer.parseInt(time);
int year=tt/10000;
int month=tt%10000/100;
int day=tt%100+1;
int n;
int []ans=new int[2];
boolean flag1=false,flag2=false;
if(IsRun(year)) monthes[2]=29;
for(int i=year;i<=9999;i++,month=1,day=1) //巧妙运用for循环的顺序,可以实现从当前日期开始往后寻找
for(int j=month;j<=12;j++,day=1)
for(int k=day;k<=monthes[j];k++)
n=i*10000+j*100+k;
String Str=String.valueOf(n);
if(ABBA(Str)&&flag1==false)
String str1=Str;
flag1=true;
ans[0]=n;
if(ABAB(Str)&&flag2==false)
String str2=Str;
flag2=true;
ans[1]=n;
if(flag1==true&&flag2==true) break;
System.out.println(ans[0]);
System.out.println(ans[1]);
回文日期 (蓝桥云) JAVA
目录
题目描述:
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赛制。
以上是关于蓝桥回文日期的主要内容,如果未能解决你的问题,请参考以下文章