每天一道算法题の回文日期

回文日期

题目链接
个人博客主页

解析: 我们知道,回文数就是折半之后前后两两对称的数,所以,我们可以直接通过一些方法来对比前后的数是否相等

  • 方法1:将数转换为字符串,分别取前后索引进行对比(可以用循环,也可以直接写出所有情况,或者利用字符串截取和StringBuilder的反转函数reveser)

    • StringBuilder:StringBuilder是一个可变字符串,可以用其对字符串进行封装,从而进一步操作字符串,常用方法有:
      • append(String str) 追加字符串
      • resever(String str) 将str翻转并返回
  • 方法2:利用取余得到每一位上的数,进而比较,例:

    20200202%100 = 02 = 2 可知日期为2号

根据题目的要求,测试实例为10000101≤N≤89991231,也就是输入的日期范围,因为日期要求为8位数,故而我们应该判断的日期范围应为[输入日期,99999999],

又因为是从输入日期开始后的下一个回文日期,故而判断范围的起始应该为输入日期+1,这一步是为了消除当输入日期本身就是一个回文日期从而影响结果的准确性。

利用循环,遍历日期范围,利用上述的两种方式,判断是否为回文日期,在回文日期之后,我们可以再追加一个ABABBABA型回文数的判断,因为已经是回文数了,所以根据前后对称的原则,到这里我们只需要判断[0,2)字符串和[2,4)字符串是否相等即可,如果02和24相等,那么后面也必然是相等的。做完上面这些,我们就可以获取到[输入日期,99999999]之间的所有回文日期和ABABBABA型回文日期了,但是,这里面并不是每一个都符合日期要求,比如,一年不能超过12个月,一个月最多只能有31天,故而,从右往左,1、2位组合的最大数值不能大于31,3,4位组合的最大数不能超过12,(5、6)和(7、8)分别是(3,4)和(1,2)的反序,

例如,(1,2)的取值为:【01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19…31】

对应的(7,8)的取值为(1,2)的反序,及【10,20,30,40,50,60,70,80,90,01,11,21,31,41…13】

(3,4)、(5,6)同理,我们可以利用链表来存储这些数据,当我们获取到一个日期时,先判断它是否是一个合理的日期,如果不是,也就没必要判断它是否是回文日期了。以上就是全部的内容解析了!

总结 :先循环遍历所有可能的日期,再利用日期合法性筛选不合法的日期,对于合法的日期,判断它是否为回文数,如果是,再判断是否为ABABBABA型回文数。

源码如下:

	//存放天数的反串
	static List<Integer> dayReseveValue = new ArrayList<>();
	//存放月份的反串
	static List<Integer> MoneyReseveValue = new ArrayList<Integer>();
	static {
		dayReseveValue.add(1);
		dayReseveValue.add(10);
		dayReseveValue.add(11);
		dayReseveValue.add(20);
		dayReseveValue.add(21);
		dayReseveValue.add(30);
		dayReseveValue.add(40);
		dayReseveValue.add(50);
		dayReseveValue.add(60);
		dayReseveValue.add(70);
		dayReseveValue.add(80);
		dayReseveValue.add(90);
		
		for(int i=1;i<=31;i++) {
			//01对应10,但是01没有0,所以要默认*10
			if(i<10)
				MoneyReseveValue.add(i*10);
			else
				MoneyReseveValue.add(Integer.parseInt(revese(i+"")));
		}	
	}
	
	public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        //在此输入您的代码...
        int date = scan.nextInt();//输入日期
        boolean firstPalindrome = true;//回文数输出判定条件
        
        for(int i=date+1;i<99999999;i++) {

        	if(i%100>31||i/100%100>12||!isMonthOk(((int)(i/Math.pow(10, 6))))||!isDayOK(i/10000%100)) {
        		continue;
        	}
//        	if(i%100>31||((int)(i/Math.pow(10, 6)))>31||(i/10000%100)>12||(i/100%100)>12)
//        		continue;
        	//判断回文数
        	//revese((i+"").substring(4,8))) 取4位反转
        	if((i+"").substring(0,4).equals(revese((i+"").substring(4,8)))) {
        		//只输出一次回文数,后面的回文都用来判断是否为ABABBABA,一旦都找到,结束循环
        		//回文和ABABBABA型回文可以同时为一个数
        		if(firstPalindrome) {
        			firstPalindrome=!firstPalindrome;
        			System.out.println(i);
        		}
        		if(isABABBABA(i+"")) {
    				System.out.println(i);
        			break;
    			}
        	}
        }
        scan.close();
    }
	
	//判断年份部分中对应月份部分是否合法
	static boolean isMonthOk(int num) {
		return MoneyReseveValue.contains(num);
	}
	
	//判断月份部分对应天数部分是否合法
	static boolean isDayOK(int num) {
		return dayReseveValue.contains(num);
	}
	
	
	//判断是否为ABABBABA型回文数
	static boolean isABABBABA(String date) {
		//因为判断的都是回文数,所以abab型只需要判断02和04这个区间
		return date.substring(0, 2).equals(date.substring(2,4));
	}
	
	//将形参字符串反转并返回
	static String revese(String str) {
		return new StringBuilder(str).reverse().toString();
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值