一、题目
警察在侦破一个案件时,得到了线人给出的可能犯罪时间,形如 “HH:MM” 表示的时刻。根据警察和线人的约定,为了隐蔽,该时间是修改过的,解密规则为:利用当前出现过的数字,构造下一个距离当前时间最近的时刻,则该时间为可能的犯罪时间。每个出现数字都可以被无限次使用。
备注:
可以保证线人给定的字符串一定是合法的。 例如,“01:35” 和 “11:08” 是合法的,“1:35” 和 “11:8” 是不合法的。
最近的时刻有可能在第二天
二、输入
形如HH:SS的字符串,表示原始输入
三、输出
形如HH:SS的字符串,表示推理出来的犯罪时间
四、示例
示例一
输入:
18:52
输出:
18:55
说明:利用数字1, 8, 5, 2构造出来的最近时刻是18:55,是3分钟之后。结果不是18:51因为这个时刻是18小时52分钟之后。
示例二
输入:
23:59
输出:
22:22
说明:利用数字2, 3, 5, 9构造出来的最近时刻是22:22。 答案一定是第二天的某一时刻,所以选择可构造的最小时刻为犯罪时间。
五、题解
- 本题考查的是工程实现能力,看似简单,没想清楚写出来可能就是一坨代码
- 本题实现使用了计算机思维的简单暴力算法,有一种暴力美感。时间复杂度就是 1440 次计算(一天的分钟数)
5.1 Java 实现
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实现
# 是否有效的小时和分钟
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))