一、题目

警察在侦破一个案件时,得到了线人给出的可能犯罪时间,形如 “HH:MM” 表示的时刻。根据警察和线人的约定,为了隐蔽,该时间是修改过的,解密规则为:利用当前出现过的数字,构造下一个距离当前时间最近的时刻,则该时间为可能的犯罪时间。每个出现数字都可以被无限次使用。

备注:

可以保证线人给定的字符串一定是合法的。
例如,“01:35” 和 “11:08” 是合法的,“1:35” 和 “11:8” 是不合法的。

最近的时刻有可能在第二天

二、输入

形如HH:SS的字符串,表示原始输入

三、输出

形如HH:SS的字符串,表示推理出来的犯罪时间

四、示例

示例一

1
2
3
4
5
输入:
18:52

输出:
18:55

说明:利用数字1, 8, 5, 2构造出来的最近时刻是18:55,是3分钟之后。结果不是18:51因为这个时刻是18小时52分钟之后。

示例二

1
2
3
4
5
输入:
23:59

输出:
22:22

说明:利用数字2, 3, 5, 9构造出来的最近时刻是22:22。 答案一定是第二天的某一时刻,所以选择可构造的最小时刻为犯罪时间。

五、题解

  1. 本题考查的是工程实现能力,看似简单,没想清楚写出来可能就是一坨代码
  2. 本题实现使用了计算机思维的简单暴力算法,有一种暴力美感。时间复杂度就是 1440 次计算(一天的分钟数)

5.1 Java 实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package org.stone.study.algo.ex202411;

import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;

/**
* 大厂算法:解密犯罪时间
* 下一个最近的时间
**/
public class NextClosestTime {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String time = sc.nextLine();

String ans = getNextClosestTime(time);
System.out.println(ans);
}

public static String getNextClosestTime(String time) {
// 提取时间中非:的字符,并将其转换为数字放到set 中
Set<Integer> digits = new HashSet<>();
for (int i = 0; i < time.length(); i++) {
if (time.charAt(i)!= ':') {
digits.add(time.charAt(i) - '0');
}
}
String[] parts = time.split(":");
int hours = Integer.parseInt(parts[0]);
int minutes = Integer.parseInt(parts[1]);

// 从当前时间开始,逐个尝试下一个时间是否有效。最多尝试1440次(24小时),即一天的时间。
for (int delta = 1; delta <= 1440; delta++) {
int nextTime = (hours * 60 + minutes + delta) % 1440;
int newHours = nextTime / 60;
int newMinutes = nextTime % 60;

if(!validTime(newHours, newMinutes, digits)) {
continue;
}

return String.format("%02d:%02d", newHours, newMinutes);
}

return "";
}

// 判断时间是否有效时间,数字是否在允许的数字集合中
public static boolean validTime(int hours, int minutes, Set<Integer> digits) {
if (hours > 23 || minutes > 59) {
return false;
}

int[] time = {hours / 10, hours % 10, minutes / 10, minutes % 10};
for (int digit : time) {
if (!digits.contains(digit)) {
return false;
}
}

return true;
}
}

5.2 Python实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 是否有效的小时和分钟
def is_valid(hour, minute):
return 0 <= hour < 24 and 0 <= minute < 60

# 找到下一个最近的时间:数字可以重复使用,可以跨天
def next_closest_time(input_time):
# 提取输入时间的各个数字
digits = set(input_time.replace(':', ''))
digits = sorted(digits)

hour, minute = map(int, input_time.split(':'))

for delta in range(1, 1440):
# 计算下一个时间,最多尝试1440分钟(24小时)
next_time = (hour * 60 + minute + delta) % (24 * 60)

new_hour = next_time // 60
new_minute = next_time % 60
# 是否有效时间
if not is_valid(new_hour, new_minute):
continue

new_time = f'{new_hour:02d}:{new_minute:02d}'
# 检查新时间的每个数字是否在输入时间的数字集合中
if all(digit in digits for digit in new_time.replace(':', '')):
return new_time

return None

if __name__ == '__main__':
input_time = input()
print(next_closest_time(input_time))