目录
题目
代码
AC结果
思路:
一、获取数据
二、验证日期合法性
三、去重
四、排序
五、主方法中调用&输出
题目
1229. 日期问题 - AcWing题库https://www.acwing.com/problem/content/description/1231/
代码
import java.util.Scanner;
public class Main {
public static void main(String[] args){
Scanner input = new Scanner(System.in);
String[] str = input.nextLine().split("\\/");
int value0 = Integer.parseInt(str[0]);
int value1 = Integer.parseInt(str[1]);
int value2 = Integer.parseInt(str[2]);
String[] ans = new String[3];
//0:年 1:月 2:日
if(check(value0,value1,value2)){
if(value0 >= 60){
ans[0] = "19" + str[0] + "-" + str[1] + "-" + str[2];
}else {
ans[0] = "20" + str[0] + "-" + str[1] + "-" + str[2];
}
}else {
ans[0] = "false";
}
//0:月 1:日 2:年
if(check(value2,value0,value1)){
if(value2 >= 60){
ans[1] = "19" + str[2] + "-" + str[0] + "-" + str[1];
}else {
ans[1] = "20" + str[2] + "-" + str[0] + "-" + str[1];
}
}else {
ans[1] = "false";
}
//0:日 1:月 2:年
if(check(value2,value1,value0)){
if (value2 >= 60){
ans[2] = "19" + str[2] + "-" + str[1] + "-" + str[0];
}else {
ans[2] = "20" + str[2] + "-" + str[1] + "-" + str[0];
}
}else {
ans[2] = "false";
}
distinct(ans);
rank(ans);
//输出
for(int i = 0; i < ans.length; i++){
if(ans[i] == "false"){
continue;
}
System.out.println(ans[i]);
}
}
//排序
public static void rank(String[] ans){
String temp = "";
//年排序
for(int i = 0; i < ans.length - 1; i++){
for(int j = i + 1; j < ans.length; j++){
if(ans[i] == "false" || ans[j] == "false"){
continue;
}else if (Integer.parseInt(ans[i].substring(0,4)) > Integer.parseInt(ans[j].substring(0,4))){
temp = ans[i];
ans[i] = ans[j];
ans[j] = temp;
}
}
}
//月排序
for(int i = 0; i < ans.length - 1; i++){
for(int j = i + 1; j < ans.length; j++){
if(ans[i] == "false" || ans[j] == "false"){
continue;
}else if(Integer.parseInt(ans[i].substring(5,7)) > Integer.parseInt(ans[j].substring(5,7))){
if(Integer.parseInt(ans[i].substring(0,4)) == Integer.parseInt(ans[j].substring(0,4))){
temp = ans[i];
ans[i] = ans[j];
ans[j] = temp;
}
}
}
}
//日排序
for(int i = 0; i < ans.length - 1; i++){
for(int j = i + 1; j < ans.length; j++){
if(ans[i] == "false" || ans[j] == "false"){
continue;
}else if(Integer.parseInt(ans[i].substring(8,10)) > Integer.parseInt(ans[j].substring(8,10))){
if(Integer.parseInt(ans[i].substring(0,4)) == Integer.parseInt(ans[j].substring(0,4)) && Integer.parseInt(ans[i].substring(5,7)) == Integer.parseInt(ans[j].substring(5,7))){
temp = ans[i];
ans[i] = ans[j];
ans[j] = temp;
}
}
}
}
}
//数值合法性
public static boolean check(int year,int month,int day){
//数据合法性
if(month == 0 || day == 0 || month > 12 || day > 31) {
return false;
}
boolean isLeapYear = year % 4 == 0;
if(month <= 7 && month % 2 == 1 || month > 7 && month % 2 == 0){//判断大月
if(day > 31){
return false;
}
}else if(month <= 7 && month % 2 == 0 || month > 7 && month % 2 == 1){//判断小月
if(month == 2){//判断闰年&平年的2月
if (isLeapYear){
if(day > 29){
return false;
}
} else if (!isLeapYear){
if (day > 28){
return false;
}
}
}else if(day > 30){
return false;
}
}
return true;
}
//去重
public static void distinct(String[] ans){
ans[0] = ans[0].equals(ans[1]) ? "false" : ans[0];
ans[0] = ans[0].equals(ans[2]) ? "false" : ans[0];
ans[1] = ans[1].equals(ans[2]) ? "false" : ans[1];
}
}
AC结果
思路:
这题整体思路并不难,就是需要考虑周全。题目意思是输入一个A/B/C格式的日期,然后输出其可能表示的日期。有可能是A年B月C日、C年A月B日、C年B月A日三种可能性。除此之外,还需要对他们的数值进行判断,确保生成的是一个合法的正常的日期。然后对答案进行去重排序,即可输出。
一、获取数据
Scanner input = new Scanner(System.in);
String[] str = input.nextLine().split("\\/");
int value0 = Integer.parseInt(str[0]);
int value1 = Integer.parseInt(str[1]);
int value2 = Integer.parseInt(str[2]);
String[] ans = new String[3];
题目输入格式为“A/B/C”,所以我们就以【斜杠】为分界,将三个数据分别存入value0、value1、value2三个int类型的变量之中。String类型数组ans用于存储生成的日期。
二、验证日期合法性
//数值合法性
public static boolean check(int year,int month,int day){
//数据合法性
if(month == 0 || day == 0 || month > 12 || day > 31) {
return false;
}
boolean isLeapYear = year % 4 == 0;
if(month <= 7 && month % 2 == 1 || month > 7 && month % 2 == 0){//判断大月
if(day > 31){
return false;
}
}else if(month <= 7 && month % 2 == 0 || month > 7 && month % 2 == 1){//判断小月
if(month == 2){//判断闰年&平年的2月
if (isLeapYear){
if(day > 29){
return false;
}
} else if (!isLeapYear){
if (day > 28){
return false;
}
}
}else if(day > 30){
return false;
}
}
return true;
}
这个方法是用于对生成的日期进行合法性判断。此处不需要对“年”进行验证,后面会详说。这里只需要对月份和日期进行合法性验证。
规则:
【1】“月”和“日”不可以为0
【2】“月”不可以大于12
【3】“日”不可大于31(具体月份后续具体分析,但是超过31就必定是不合法的)
【4】1、3、5、7、8、10、12月的“日”不大于31
【5】4、6、9、11月的“日”不大于30
【6】2月的“日”,闰年为29,平年不大于28
简而言之,就是月份符合小学时候学的“拳峰特点”。年份对4取余,观察结果是否为0,若是则为闰年,否则为平年。上述各个条件,但凡有一个不满足,就返回false。若都满足,则这个生成的日期是合法的,返回true。
三、去重
//去重
public static void distinct(String[] ans){
ans[0] = ans[0].equals(ans[1]) ? "false" : ans[0];
ans[0] = ans[0].equals(ans[2]) ? "false" : ans[0];
ans[1] = ans[1].equals(ans[2]) ? "false" : ans[1];
}
因为生成的日期最多有三个。用第一个日期与第二第三个日期进行比对,是否相同,若相同则将第一个日期替换为字符串“false”。然后,用第二个日期与第三个日期进行比对,相同也是同样处理。替换为“false”的意思是,将其变为不合法的状态。
四、排序
//排序
public static void rank(String[] ans){
String temp = "";
//年排序
for(int i = 0; i < ans.length - 1; i++){
for(int j = i + 1; j < ans.length; j++){
if(ans[i] == "false" || ans[j] == "false"){
continue;
}else if (Integer.parseInt(ans[i].substring(0,4)) > Integer.parseInt(ans[j].substring(0,4))){
temp = ans[i];
ans[i] = ans[j];
ans[j] = temp;
}
}
}
//月排序
for(int i = 0; i < ans.length - 1; i++){
for(int j = i + 1; j < ans.length; j++){
if(ans[i] == "false" || ans[j] == "false"){
continue;
}else if(Integer.parseInt(ans[i].substring(5,7)) > Integer.parseInt(ans[j].substring(5,7))){
if(Integer.parseInt(ans[i].substring(0,4)) == Integer.parseInt(ans[j].substring(0,4))){
temp = ans[i];
ans[i] = ans[j];
ans[j] = temp;
}
}
}
}
//日排序
for(int i = 0; i < ans.length - 1; i++){
for(int j = i + 1; j < ans.length; j++){
if(ans[i] == "false" || ans[j] == "false"){
continue;
}else if(Integer.parseInt(ans[i].substring(8,10)) > Integer.parseInt(ans[j].substring(8,10))){
if(Integer.parseInt(ans[i].substring(0,4)) == Integer.parseInt(ans[j].substring(0,4)) && Integer.parseInt(ans[i].substring(5,7)) == Integer.parseInt(ans[j].substring(5,7))){
temp = ans[i];
ans[i] = ans[j];
ans[j] = temp;
}
}
}
}
}
遍历ans二维数组,依次进行年排序、月排序和日排序。优先进行“年”的排序,将年份按大小的排列好。此时再进行月排序,排序前需要对两个待排序的日期的年份进行判断。如果年份不同,则不需要进行换位操作;如果年份一样,就可以进行换位操作。日排序也是同样的道理,需要年份和月份都相同的时候再对日期进行排序。
五、主方法中调用&输出
//0:年 1:月 2:日
if(check(value0,value1,value2)){
if(value0 >= 60){
ans[0] = "19" + str[0] + "-" + str[1] + "-" + str[2];
}else {
ans[0] = "20" + str[0] + "-" + str[1] + "-" + str[2];
}
}else {
ans[0] = "false";
}
//0:月 1:日 2:年
if(check(value2,value0,value1)){
if(value2 >= 60){
ans[1] = "19" + str[2] + "-" + str[0] + "-" + str[1];
}else {
ans[1] = "20" + str[2] + "-" + str[0] + "-" + str[1];
}
}else {
ans[1] = "false";
}
//0:日 1:月 2:年
if(check(value2,value1,value0)){
if (value2 >= 60){
ans[2] = "19" + str[2] + "-" + str[1] + "-" + str[0];
}else {
ans[2] = "20" + str[2] + "-" + str[1] + "-" + str[0];
}
}else {
ans[2] = "false";
}
distinct(ans);
rank(ans);
//输出
for(int i = 0; i < ans.length; i++){
if(ans[i] == "false"){
continue;
}
System.out.println(ans[i]);
}
在主方法中按规则分别枚举每种情况(例如:输入为“02/03/04”,枚举出来02年3月4日、04年2月3日、04年3月2日三种情况)。然后此处需要对年份作单独的判断,由题目可知日期的有效时间段在1960-2059。那意味着题目输入的任意一个年份都是合法的,但是需要判断是20世纪还是21世纪。当年份为[60,99]在是20世纪,当年份为[0,59]则表示在21世纪。对生成的日期调用check方法检验合法性,若合法则将生成的日期存入ans对应位置,年月日之间用“-”链接。否则,将字符串“false”传入ans当前对应位置,表示该个生成的日期不合法。
得到的结果存入ans数组中,然后遍历ans数组,如果是“false”就跳过当前,如果不是那就输出对应生成的日期。