蓝桥杯:日期问题

题目描述

输入描述

输出描述

输入输出样例

输入样例

输出样例

思路分析

AC代码(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

思路分析

        首先,题目会给我们一个字符串,是以 AA-BB-CC 的格式给出。

        题目说了,只有可能有三种日期:

        * 年/月/日的格式的,也就是AA为年,BB为月,CC为日

        * 月/日/年的格式的,也就是AA为月,BB为日,CC为年

        * 日/月/年的格式的,也就是AA为日,BB为月,CC为年

        而且,年的话是从1960-2059,也就是说,题目给出的年份只包含后面两位,前面两位是需要我们补充的,比如说后面两位是小于60,那么肯定是20年的,大于等于60,那肯定就是19年的。

        再接着是月份和日期,我们需要判断我们拼接的日期是否满足条件,比如说2002年02月29日,这个日期肯定是不合法的,因为2002年不是闰年,2月只能由28天。

        同样,2002年02月00日也是不合法的,所以我们需要在拼接日期的时候判读该日期是否合法。在日期合法的前提上再去拼接成字符串。

        最后就是日期的去重和排序问题了。

        去重的意思是,同样的日期我们只能输出一次。

        排序就是,我们根据日期,从小到大进行比较排序。

        这种题目难度不是很难,主要是考的细,需要我们注意一点。

AC代码(Java)

        题目要求使用升序排序,一些提供排序方法都是默认升序进行排序的,并且字符串的升序是根据字典序进行升序排序的,符合题目要求的按照日期升序排序。

        字典序简单提一嘴,就是字符串升序排序,是依次对比每个字符,如果字符相同,就继续比较下一个字符,直到比较出大小。

        所以我们直接使用TreeSet即可,这个是去重升序排序的。

import java.util.*;
// 1:无需package
// 2: 类名必须Main, 不可修改

public class Main {

    static Set<String> set = new TreeSet<>(); //存放可能的日期
    static int[] date ={0,31,29,31,30,31,30,31,31,30,31,30,31}; //月份表,i代表day1[i]代表月份

    public static void main(String[] args) {

        Scanner scan = new Scanner(System.in);
        String str = scan.next();
        scan.close();
        //切割出来,分隔成三部分
        String[] strs = str.split("/");

        //拼凑成日期存放到set中
        check(strs);

        //打印结果
        for(String date : set)
            System.out.println(date);
    }
    //拼凑成日期存放到set中
    public static void check(String[] strs){
        /* 因为日期可能有三种方法,我们分别处理*/
        //第一种是年/月/日的,根据切割字符串来放入,strs[0]代表年份,strs[1]代表月份,strs[2]代表日期
        linkDate(strs[0],strs[1],strs[2]);
        //第二种是月/日/年的,那么根据strs来放入,strs[0]代表月份,strs[1]代表日期,strs[2]代表年份
        linkDate(strs[2],strs[0],strs[1]);
        //第二种是日/月/年的,那么根据strs来放入,strs[0]代表日期,strs[1]代表月份,strs[2]代表年份
        linkDate(strs[2],strs[1],strs[0]);
    }
    //拼凑日期
    public static void linkDate(String year,String month,String day){
        //确定具体年份,最后两年低于60就是20年的,高于等于60就是19年的
        year = Integer.parseInt(year) < 60 ? "20"+year : "19"+year;
        /* 判断月份是否合法(1-12之间) */
        int target = Integer.parseInt(year);
        //修改2月的值,如果是闰年就是29天,不然就是28天
        date[2] = ((target%4==0&&target%100!=0) || (target%400 == 0)) ? 29 : 28;
        //month是月份,转换成整数,然后判断day是否在合法范围内[0-day[month]]
        int intMonth = Integer.parseInt(month);
        //如果月份不合法(不在1-12之间)
        if(intMonth<1 || intMonth>12) return ;
        int intDay = Integer.parseInt(day);
        //如果不在范围内,直接结束本方法
        if(intDay<1 || intDay>date[intMonth]) return ;
        /* 年份,月份,日期,都需要满足yyyy-MM-dd,也就是年份4位,月份日期两位*/
        if(month.length() < 2) month = 0+month;
        if(day.length() < 2) day = 0+day;
        /* 都处理好了,放入set中进行去重处理*/
        set.add(year+"-"+month+"-"+day);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值