蓝桥杯java组 日期问题

题目描述

小明正在整理一批历史文献。这些历史文献中出现了很多日期。小明知道这些日期都在1960年1月1日至2059年12月31日。令小明头疼的是,这些日期采用的格式非常不统一,有采用年/月/日的,有采用月/日/年的,还有采用日/月/年的。更加麻烦的是,年份也都省略了前两位,使得文献上的一个日期,存在很多可能的日期与其对应。

比如02/03/04,可能是2002年03月04日、2004年02月03日或2004年03月02日。

给出一个文献上的日期,你能帮助小明判断有哪些可能的日期对其对应吗?

输入:

一个日期,格式是"AA/BB/CC"。 (0 <= A, B, C <= 9)

输入:

输出若干个不相同的日期,每个日期一行,格式是"yyyy-MM-dd"。多个日期按从早到晚排列。

样例输入:

02/03/04

样例输出:

2002-03-04
2004-02-03
2004-03-02

代码

import java.util.*;  
  
/**  
 * @author Fancier  
 * @version 1.0  
 * @description: 日期问题  
 * @date 2024/3/7 12:30  
 */  
public class Main {  
    public static void main(String[] args) {  
        new Solution();  
    }  
}  
class Solution {  
    Scanner scanner = new Scanner(System.in);  
    Set<String> set = new HashSet<>();  
    Set<Integer> smallMonth = new HashSet<Integer>(){{  
        add(4);  
        add(6);  
        add(9);  
        add(11);  
    }};  
    String[] src;  
    int[] path;  
    ArrayList<String> result = new ArrayList<>();  
    boolean[] isVisited = new boolean[3];
      
    public Solution() {  
        String date = scanner.next();  
        src = date.split("/");  
        dfs(path = new int[3], 0);  
        Collections.sort(result);  
        for (String s : result) {  
            if (set.add(s)) {  
                System.out.println(s);  
            }  
        }  
    }  
  
    public boolean check(String prefix) {  
        int month = Integer.parseInt(src[path[1]]),  
            day = Integer.parseInt(src[path[2]]),  
            year = Integer.parseInt(prefix + src[path[0]]);  
        if (month < 13 && day < 32 && month > 0 && day > 0 && year >= 1960 && year <= 2059) {  
            if (month == 2) {  
                if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {  
                    return day <= 29;  
                } else  
                    return day <= 28;  
            }  
            return !smallMonth.contains(month) || day != 31;  
        }  
        return false;  
    }  
    //第二个位置数不可能是年, 第三个位置的数不可能是月  
    public void dfs(int[] path, int index) {  
        if (index == 3) {  
            if (path[0] == 1 || path[1] == 2) return;  
            if (check("19")) result.add("19" + src[path[0]] + "-" + src[path[1]] + "-" + src[path[2]]);  
            if (check("20")) result.add("20" + src[path[0]] + "-" + src[path[1]] + "-" + src[path[2]]);  
        }  
        for (int i = 0; i < 3; i++) {  
            if (!isVisited[i]) {  
                path[index] = i;  
                isVisited[i] = true;  
                dfs(path, index + 1);  
                isVisited[i] = false;  
            }  
        }  
    }  
}

题解

这道题理解起来不难, 看起来也容易的, 但是真正做起来会有很多细节的地方恶心人
那么咱们就来说说这些细节

  1. 很容易想到全排列但有些情况是不存在的
    仔细读题会发现原字符串中的第二个数不可能是答案中的年, 第三个数不可能是答案中的月
  2. 会出现重复的情况要去重
  3. 要考虑闰年大月小月和还有日期范围
  4. 还有字符串转换成数字
  5. 最后当你以为手到擒来的时候, 才发现没考虑 多个日期按从早到晚排列 还要排序!!!

解决方法

  1. 用一个数组来保存排列后的下标情况 去掉不符合的
  2. 用set去重
  3. 这个很容易解决
  4. 这个也是
  5. 用List保存全部答案后再排序

具体代码参上

好的!本次分享到这就结束了
如果对铁汁你有帮助的话,记得点赞👍+收藏⭐️+关注➕
我在这先行拜谢了:)

  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值