3489. 星期几
问题重述:
已知 11 年 11 月 11 日是星期一。
现在给定一个日期,请你判断是星期几。
注意闰年的 22 月有 2929 天。
满足下面条件之一的是闰年:
- 年份是 44 的整数倍,而且不是 100100 的整数倍;
- 年份是 400400 的整数倍。
输入格式
输入包含多组测试数据。
每组数据占一行,包含一个整数 dd 表示日,一个字符串 mm 表示月,一个整数 yy 表示年。
月份 1∼12,依次如下所示:
January, February, March, April, May, June, July, August, September, October, November, December
输出格式
每组数据输出一行结果,输出一个字符串表示给定日期是星期几。
周一至周日依次如下所示:
Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday
数据范围
1000≤y≤30001000≤y≤3000,
给定日期保证合法。
每个输入最多包含 100100 组数据。
输入样例:
9 October 2001
14 October 2001
输出样例:
Tuesday
Sunday
问题分析:
题目要求计算某一天为周几,我们已知1 年 1 月 1 日是星期一,那么我们只需要算出从1 年 1 月 1 日到我们当前这一个日期之间的天数,然后用总天数对7求余数,余0则为周日,其他的则为对应的星期几。需要注意的是闰年的天数比普通的年份天数多一天,需要加上去。
这道题还需要注意的是,这道题并不是给一个数据输入一个数据,而是一次性给了多组数据,这个时候我们就不能再用Scanner来录入数据了,因为最后需要一个结束,但给定的数据是没有结束标记的,所以我们要使用BufferedReader(字符缓冲输入流)来输入数据。
解法:
模拟,按照题目要求,一步一步算即可得出结果
解题:
代码:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Objects;
/**
* 已知 1 年 1 月 1 日是星期一。
* 现在给定一个日期,请你判断是星期几。
* 注意闰年的 2 月有 29 天。
* 满足下面条件之一的是闰年:
* 年份是 4 的整数倍,而且不是 100 的整数倍;
* 年份是 400 的整数倍。
* 输入格式
* 输入包含多组测试数据。
* 每组数据占一行,包含一个整数 d 表示日,一个字符串 m 表示月,一个整数 y 表示年。
* 月份 1∼12,依次如下所示:
* January, February, March, April, May, June, July, August, September, October, November, December
* 输出格式
* 每组数据输出一行结果,输出一个字符串表示给定日期是星期几。
* 周一至周日依次如下所示:
* Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday
* 数据范围
* 1000≤y≤3000,
* 给定日期保证合法。
* 每个输入最多包含 100 组数据。
* 输入样例:
* 9 October 2001
* 14 October 2001
* 输出样例:
* Tuesday
* Sunday
*/
public class Main{
public static int[] monthDays = {0,31,28,31,30,31,30,31,31,30,31,30,31};
public static String[] month = {" ","January", "February","March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
public static String[] week = {"Sunday","Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
public static void main(String[] args) throws IOException {
//计算一月到每个月的天数
for(int i = 1;i <= 12;i++){
monthDays[i] += monthDays[i-1];
}
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
ArrayList<String> data = new ArrayList<>();
String str;
//读取每一组数据
while((str = br.readLine()) != null){
//读取到的数据不为空,则对当前是星期几进行判断
int i = d(0,str)%7;
data.add(week[i]);
}
for (int i = 0,len = data.size(); i < len; i++) {
System.out.println(data.get(i));
}
}
//计算天数
public static int d(int y,String str){
//将每一组的字符串分离成年月日
String []array = str.split(" ");
int i = Integer.parseInt(array[2]);
//每一组数据进行计算前都要进行置零
y = 0;
//计算年份包含多少天
for (int j = 1; j < i; j++) {
if (isrun(j)){
y += 366;
}else{
y += 365;
}
}
//月份
int m = 0;
for (int j = 1; j < 13; j++) {
if (Objects.equals(array[1],month[j])){
y += monthDays[j-1];
m = j;
}
}
//如果当前年份为闰年,且月份在二月之后,那么需要把二月多的一天加上
if (isrun(i) && m>2){
y += 1;
}
//天数
y += Integer.parseInt(array[0]);
return y;
}
//判断是否是闰年
public static boolean isrun(int year){
if(year % 400 == 0){
return true;
}
if(year % 4 == 0 && year % 100 != 0){
return true;
}
return false;
}
}
代码分析:
首先定义了月份和星期的字符串数组,月份数组用于对数据中的月份进行判断,星期数组用于对最后结果进行输出。使用前缀和计算出普通年份的开始到各个月份的天数(计算对应的月份天数就不需要每一次都进行循环了,节省时间),使用BufferedReader(字符缓冲输入流)来对数据进行处理,使用一个while循环,当读取的下一行不为空时,对读入的数据调用计算天数的方法进行处理,为空则读取完毕。然后对天数进行处理,即可得出对应的星期几。
调用天数的方法解析:
首先对传入的字符串进行分隔,分割出年月日,分别计算年月日对应的天数,使用年份计算从年到当前年份之间总共有多少天,在计算时需要判断年份是否为闰年,闰年则需要多加二月的一天。然后进行月份计算,使用当前月份和month数组进行比较,再从monthDays数组中得到年初到当前月份的天数,但是需要注意,如果当前年份为闰年,并且月份超过二月,那么需要加上一天(因为我们的monthDays计算的时普通年份的天数),最后再加上当前日期的天数,返回的y就是从1 年 1 月 1 日到当前日期的天数。
总结:
这道题就是需要注意在计算月份对应天数时,要考虑当前年份是不是闰年,闰年那么就需要加上2月多出来的那一天 。