算法:回文日

12月2日,浏览资讯的时候无意间发现了李永乐老师在Bilibili发了一条动态。

 

 这完全勾起了我的兴趣,便用实验课时间写代码计算一下(所谓写代码半小时,改BUG一下午)

当时由于刚刚进入面向对象不久,也没有学习Date和日历的常用类,所以使用的方法是一般的字符串的方法,在最后有使用SimpleDateFormat的方法。

  • 使用一般方法

//首先定义今天(12月2日)的日期
    static int year = 2021;
    static int month = 12;
    static int day = 2;
//由于整数类型会忽略没有意义的“0”,所以需要将数字类型转化为字符串,然后补齐“0”
    String yearstr = String.valueOf(year);
    String monthstr = String.valueOf(month);
    String daystr = String.valueOf(day);
    if (monthstr.length() == 1) {
        monthstr = 0 + monthstr;
    }
    if (daystr.length() == 1) {
        daystr = 0 + daystr;
    }
  String date =yearstr+monthstr+daystr;
 

之后是最关键的步骤:date字符串是否满足回文日的格式,以及date字符串是否是一个日期。

满足天数,则必须大月时,天数不大于31天,小月时,天数不大于30天。平年时,2月的天数不大于28天,闰年的时候,2月的天数不超过29天。

//这里定义了一个方法,用来检测是否是年月日。
public static boolean fix(int month, int day) {
//如果当前是大月,则天数不能超过31天。
if ((month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12)) { if (day <=31) { return true; }
//如果当前是小月,则天数不能超过30天 }
else if ((month == 4 || month== 6 || month == 9 || month == 11)) { if (day <= 30) { return true; } } else if (month == 2) { //如果当前是2月份,那么闰年的时候,天数不能超过29天,平年则不超过28天。闰年的定义指的是年份是4但不是100的倍数,或者是400的倍数。 if ((year % 4 == 0&&year%100!=0)||(year%400==0)) { if (day <= 29) { return true; } } else{ if (day <= 28) { return true; } } } return false; }

做完做些之后我们只要对字符串进行比较。

字符串是yyyyMMdd的形式,只要满足字符串下标为0的字符和7相同,1和6相同…即可。在里面进行计数,最后让day进行自增或者自减。

if(flag&&date.charAt(0)==date.charAt(7)&&date.charAt(1)==date.charAt(6)&&date.charAt(2)==date.charAt(5)&&date.charAt(3)==date.charAt(4)){
                //这里的flag是上一个方法的返回值。
          System.out.println(date);
          num++;
          
}
day++;//day--;
 

最后需要对天数进行校验。如果day在大月时超过31则月数+1,小月时超过30月数也+1。2月需要分平年和闰年。

//这里定义了两个方法,分别对应day的自增和自减,这里以自减举例。
//当前月的上一个月是大月时,将天数变为31,月数-1。如果此时月数是0,则年数-1,月数变为12。
if (day == 0 && (month==1||month-1 == 1 || month-1 == 3 || month-1 == 5 || month-1 == 7 || month-1 == 8 || month-1 == 10 || month-1 == 12)) {
            day = 31;
            month--;
            if (month == 0) {
                month = 12;
                year--;
            }
//小月和2月同理。2月需要考虑闰年和平年。

使用for(;;)进行循环,当计数达到5次后结束循环。

最终可以得到回文日如下:

20211202
20200202
20111102
20100102
20011002

20300302 下一次!
20400402
20500502
20600602
20700702

 

  • 使用SimpleDateFormat和Calendar

//首先获取今天的日期,使用SimpleDateFormat的有参构造

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); 
String format = sdf.format(new Date);
//如此获得了字符串类型的今天的日期。格式为:yyyy-MM-dd

使用Calendar类获取明天的日期。

//由于Calendar是一个抽象类,所以我们使用Calendar的子类GregorianCalendar,这里使用多态的思想创建对象。

    Calendar calendar = new GregorianCalendar();
//先调用calendar的setTime方法,然后使用add方法。
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    Calendar calendar = new GregorianCalendar();
    calendar.setTime(new Date());
//偏移量是1,即为当前日期的后一天。
    calendar.add(Calendar.DAY_OF_MONTH,1);
    String date = sdf.format(calendar.getTime());

现在只要更改偏移量,就可以得到不同的日期。

现在只要定义一个变量,作为偏移量。

static int i =1;

calendar.add(Calendar.DAY_OF_MONTH,i);

在每次最后对i进行自增即可。

现在得到的String类型的date的格式为yyyy-MM-dd,因此需要0和9相同等。

下面做回文日的判断。

if(date.charAt(0)==date.charAt(9)&&date.charAt(1)==date.charAt(8)&&date.charAt(2)==date.charAt(6)&&date.charAt(3)==date.charAt(5)){
                System.out.println(date);
                count++;
            }

由此,完整代码如下:

int count=0;
int i =1;
for (;;) {
  SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
  Calendar calendar = new GregorianCalendar();
  calendar.setTime(new Date());
  calendar.add(Calendar.DAY_OF_MONTH,i);
  String date = sdf.format(calendar.getTime());
  if(date.charAt(0)==date.charAt(9)&&date.charAt(1)==date.charAt(8)&&date.charAt(2)==date.charAt(6)&&date.charAt(3)==date.charAt(5)){
  System.out.println(date);
  count++;
}
  if(count==5){
    break;
  }
  i++;
}

如果要找再往前的,则将偏移值改为-i。

最终结果如下:

2021-12-02
2020-02-02
2011-11-02
2010-01-02
2001-10-02

2030-03-02
2040-04-02
2050-05-02
2060-06-02
2070-07-02

  • 结语

由此我使用不同学习时段的两种方法计算出了下一次回文日,前者写了将近200行代码,而后者满打满算也只有30行,由此我感悟到了学海无涯。下一次回文日将出现在约8年之后,2030年3月2日。我们这一生也仅仅能经历回文日屈指可数,

正如李永乐老师所说的,珍惜时间,把握今天

posted @ 2021-12-17 16:05  Boerk  阅读(126)  评论(0)    收藏  举报