题目一:好数
题目描述
一个整数如果按从低位到高位的顺序,奇数位(个位、百位、万位 · · · )上的数字是奇数,偶数位(十位、千位、十万位 · · · )上的数字是偶数,我们就称之为“好数”。给定一个正整数 N,请计算从 1 到 N 一共有多少个好数。
输入格式
一个整数 N。
输出格式
一个整数代表答案。
样例1
输入
24输出
7
 样例2
 
输入
2024输出
150样例说明
对于第一个样例,24 以内的好数有 1、3、5、7、9、21、23,一共 7 个。
解题思路
我的思路是直接暴力做,先看奇数位,遇到不是奇数的,直接返回;如果奇数位符合条件,再看偶数位,同理遇到不是偶数的,直接返回。都符合就结果加1。
代码实现
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改
public class Main {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        //在此输入您的代码...
        int num = scan.nextInt();
        int res = 0;
        for (int i = 1; i <= num; i++) {
            res += isGoodNum(i);
        }
        System.out.println(res);
        scan.close();
    }
    private static int isGoodNum(int num) {
        String str = String.valueOf(num);
        //先看奇数位
        for (int i = str.length() - 1; i >= 0; i -= 2) {
            if (Integer.parseInt(str.charAt(i) + "") % 2 != 0) {
                continue;
            } else return 0;
        }
        //再看偶数位
        for (int i = str.length() - 2; i >= 0; i -= 2) {
            if (Integer.parseInt(str.charAt(i) + "") % 2 == 0) {
                continue;
            } else return 0;
        }
        return 1;
    }
}题目二:神奇闹钟
题目描述
小蓝发现了一个神奇的闹钟,从纪元时间(1970 年 1 月 1 日 00:00:00 )开始,每经过 x 分钟,这个闹钟便会触发一次闹铃(纪元时间也会响铃)。这引起了小蓝的兴趣,他想要好好研究下这个闹钟。
对于给出的任意一个格式为 yyyy-MM-dd HH:mm:ss 的时间,小蓝想要知道在这个时间点之前(包含这个时间点)的最近的一次闹铃时间是哪个时间?
注意,你不必考虑时区问题。
输入格式
输入的第一行包含一个整数 T,表示每次输入包含 T 组数据。
接下来依次描述 T 组数据。
每组数据一行,包含一个时间(格式为 yyyy-MM-dd HH:mm:ss )和一个整数 x ,其中 x 表示闹铃时间间隔(单位为分钟)。
输出格式
输出 T 行,每行包含一个时间(格式为 yyyy-MM-dd HH:mm:ss ),依次表示每组数据的答案。
样例输入
2
2016-09-07 18:24:33 10
2037-01-05 01:40:43 30样例输出
2016-09-07 18:20:00
2037-01-05 01:30:00解题思路
这道题本身也不难,但是我刚开始也没什么思路,后来看了一下别人的,可能是我对时间这块还不是很熟悉,所以看了一小会儿才完全理解。接下来我将用图展示出我的思路。
首先,我们仔细读题后,可以得到以下信息:
①闹钟响的时候,用格式化时间来表示的话,秒数一定是为0的,因为起始时是0,并且是每过整数分钟,闹钟才响一次,所以我们不用关注输入的秒钟部分,直接归零即可;
②响铃时刻距纪元时间,一定是x倍数分钟,那么,也就相当于是x*60的倍数秒(1分钟等于60秒)。
那么我们就想把时间转化为秒来计算,因为秒是该题目中最小单位,方便我们算。
 
如上图,黄点表示纪元,绿方块表示后续的响铃点,相邻方块之间就表示间隔了x分钟。那么,我们用蓝色圆点输入的时刻,题目要我们找出之前最近的一次响铃时间,那么我们就一步步往前移动即可。

往前移动:
 
经过数次移动,我们找到了这个时刻:
 
然后输出即可。
那怎么用程序性的语言来描述呢?我是这样理解的:
响铃的时刻是能整除(x*60)的,所以就以这个作为判断条件。从给定的时刻开始,一分钟一分钟地判断,也就是每次往前移动一分钟,直到找出目标为止。
(为什么是一分钟一分钟地移动?因为我们说了,绿方块之间就是以分钟为单位的。)
(为什么要以秒钟来计算?因为秒钟是题目当中最小单位,方便计算。)
代码实现
看代码就懂了,顺便学了一下时间相关的API使用。
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt();
        String str[] = new String[n];
        scan.nextLine();
        for (int i = 0; i < n; i++) {
            str[i] = scan.nextLine();
        }
        //格式化输入的日期
        for (int i = 0; i < n; i++) {
            String[] times = str[i].split(" ");
            LocalDateTime ldt = LocalDateTime.parse(times[0] + " " + times[1], formatter);
            ldt = ldt.withSecond(0);
            //计算距离纪元时间多少秒
            long time = ldt.toEpochSecond(ZoneOffset.UTC);
            //将x转为秒单位
            int xSecond = Integer.parseInt(times[2]) * 60;
            //关键步骤:找出最近的倍数秒
            while (time % xSecond != 0) {
                time -= 60;//回退1分钟
            }
            //格式化输出
            ldt = LocalDateTime.ofEpochSecond(time, 0, ZoneOffset.UTC);
            System.out.println(ldt.format(formatter));
        }
    }
}
如果大家有更好的理解方式,欢迎评论区留言!



















