一、題目描述
現在,牛牛想知道:在他指定的兩個日期之間(包含這兩個日期本身),有多少個真實存在的日期是迴文的。
一個 8 位數字是迴文的,當且僅當對於所有的 從左向右數的第 i 個數字和第 9−i 個數字(即從右向左數的第 i 個數字)是相同的。
例如:
- 對於2016年11月19日,用 8 位數字 20161119 表示,它不是迴文的。
- 對於2010年1月2日,用 8 位數字 20100102 表示,它是迴文的。
- 對於2010年10月2日,用 8 位數字 20101002 表示,它不是迴文的。
輸入格式
- 輸入包括兩行,每行包括一個8位數字。
- 第一行表示牛牛指定的起始日期date1,第二行表示牛牛指定的終止日期date2。保證date1和date2都是真實存在的日期,且年份部分一定爲4位數字,且首位數字不爲0。
- 保證date1一定不晚於date2。
輸出格式
- 輸出共一行,包含一個整數,表示在date1和date2之間,有多少個日期是迴文的。
輸入樣例:
20110101
20111231
輸出樣例:
1
二、題解
方法一:枚舉 + 細節
邊界問題:當輸入樣例爲:
10000101
99991231
預期:331
輸出:305
問題出現在方法 valid
中的這段判斷,爲什麼這樣做會錯呢?
if (month == 2) {
boolean isLeep = year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
if (isLeep && day != 29 || !isLeep && day != 28)
return false;
}
import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
static int[] daysInMonth= {0,31,28,31,30,31,30,31,31,30,31,30,31};
static boolean isPali(String s) {
int l = 0, r = s.length()-1;
while (l < r) {
if (s.charAt(l++) != s.charAt(r--))
return false;
}
return true;
}
private static boolean valid(int date) {
int year = date / 10000;
int month = date % 10000 / 100;
int day = date % 100;
if (month == 0 || month > 12)
return false;
if (day == 0 || month != 2 && day > daysInMonth[month])
return false;
if (month == 2) {
boolean isLeep = year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
if (isLeep && day != 29 || !isLeep && day != 28)
return false;
}
return true;
}
public static void main(String[] args) throws IOException {
Scanner sc = new Scanner(new BufferedInputStream(System.in));
BufferedWriter w = new BufferedWriter(new OutputStreamWriter(System.out));
int begin = sc.nextInt();
int end = sc.nextInt();
int count = 0;
for (int i = begin; i <= end; i++) {
if (valid(i) && isPali(i+""))
count++;
}
System.out.println(count);
}
}
更正:把 2 月份的邏輯改爲如下代碼,則得到一個 AC
if (month == 2) {
int isLeep = year % 4 == 0 && year % 100 != 0 || year%400 == 0 ? 1 : 0;
if (day > isLeep + 28)
return false;
}
複雜度分析
- 時間複雜度:,數據強一點容易 TLE
- 空間複雜度:,
方法二:構造迴文日期
由於迴文日期是 8 位,前 4 位一定和後 4 位鏡像對稱相同。所以枚舉前四位即可。
import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
static int[] daysInMonth= {0,31,28,31,30,31,30,31,31,30,31,30,31};
private static boolean valid(int date) {
int year = date / 10000;
int month = date % 10000 / 100;
int day = date % 100;
if (month == 0 || month > 12)
return false;
if (day == 0 || month != 2 && day > daysInMonth[month])
return false;
if (month == 2) {
int isLeep = year % 4 == 0 && year % 100 != 0 || year%400 == 0 ? 1 : 0;
if (day > isLeep + 28)
return false;
}
return true;
}
public static void main(String[] args) throws IOException {
Scanner sc = new Scanner(new BufferedInputStream(System.in));
BufferedWriter w = new BufferedWriter(new OutputStreamWriter(System.out));
int begin = sc.nextInt();
int end = sc.nextInt();
int count = 0;
for (int i = 1000; i <= 9999; i++) {
int date = i, t = i;
while (t != 0){
date = date * 10 + t % 10;
t /= 10;
}
if (begin <= date && date <= end && valid(date)) {
count++;
}
}
System.out.println(count);
}
}
複雜度分析
- 時間複雜度:,
- 空間複雜度:,
附:fun story
- 普通閏年:公曆年份是 4 的倍數的,且不是 100 的倍數,爲閏年。
- 世紀閏年:公曆年份是整百數的,必須是 400 的倍數纔是世紀閏年