一、题目描述
给定一个 24 小时制(小时:分钟 "HH:MM")的时间列表,找出列表中任意两个时间的最小时间差并以分钟数表示。
示例 1:
输入:timePoints = ["23:59","00:00"] 输出:1
示例 2:
输入:timePoints = ["00:00","23:59","00:00"] 输出:0
提示:
2 <= timePoints.length <= 2 * 10^4
timePoints[i]
格式为 "HH:MM"
二、解题思路
- 将所有时间转换为从"00:00"开始的分钟数。例如,"01:00"转换为60分钟,"12:34"转换为754分钟。
- 将转换后的分钟数排序。
- 计算排序后相邻时间的分钟差,并记录最小差值。
- 由于时间是一个环形的,比如"23:59"和"00:00"之间的差值需要特别计算,所以还需要计算列表中第一个和最后一个时间的差值。
- 返回记录的最小差值。
三、具体代码
import java.util.Collections;
import java.util.List;
public class Solution {
public int findMinDifference(List<String> timePoints) {
// 如果时间点数量超过一天中的分钟数,则必定存在重复时间,直接返回0
if (timePoints.size() > 1440) return 0;
// 将时间转换为分钟数并排序
Collections.sort(timePoints, (a, b) -> {
int diff = convertToMinutes(a) - convertToMinutes(b);
return diff == 0 ? a.compareTo(b) : diff; // 如果分钟数相同,则保持原有顺序
});
int minDifference = Integer.MAX_VALUE;
int prevMinutes = convertToMinutes(timePoints.get(0));
int firstMinutes = prevMinutes;
// 遍历时间点,计算相邻时间点的分钟差
for (int i = 1; i < timePoints.size(); i++) {
int currMinutes = convertToMinutes(timePoints.get(i));
minDifference = Math.min(minDifference, currMinutes - prevMinutes);
prevMinutes = currMinutes;
}
// 计算第一个和最后一个时间点的分钟差,考虑环形时间
minDifference = Math.min(minDifference, firstMinutes + 1440 - prevMinutes);
return minDifference;
}
// 将时间转换为从"00:00"开始的分钟数
private int convertToMinutes(String time) {
String[] parts = time.split(":");
return Integer.parseInt(parts[0]) * 60 + Integer.parseInt(parts[1]);
}
}
这段代码首先定义了一个辅助方法convertToMinutes
,用于将时间字符串转换为从"00:00"开始的分钟数。然后在findMinDifference
方法中,先将时间点列表排序,接着计算相邻时间点的分钟差,并记录最小差值。最后,还需要计算列表中第一个和最后一个时间点的差值,并考虑环形时间的情况。如果时间点数量超过一天中的分钟数,则直接返回0,因为这意味着必定存在重复的时间点。
四、时间复杂度和空间复杂度
1. 时间复杂度
-
convertToMinutes
方法:该方法对每个时间字符串执行一次,它包括字符串分割和整数解析操作。字符串分割是 O(1) 操作,因为时间字符串的长度是固定的(“HH:MM”),整数解析也是 O(1) 操作。因此,convertToMinutes
方法的时间复杂度是 O(1)。 -
Collections.sort
方法:对时间点列表进行排序,排序算法通常是 O(n log n),其中 n 是列表中时间点的数量。 -
遍历时间点列表并计算最小差值:这个操作是 O(n),因为每个时间点只被访问一次。
综合以上步骤,总的时间复杂度是 O(n log n) + O(n) = O(n log n),因为排序的时间复杂度通常是主导的。
2. 空间复杂度
-
convertToMinutes
方法:该方法使用了固定数量的额外空间(用于存储分割后的字符串数组),因此空间复杂度是 O(1)。 -
排序:如果使用的是类似于快速排序的算法,那么空间复杂度是 O(log n),这是因为递归调用栈的深度。
-
额外变量:
minDifference
、prevMinutes
和firstMinutes
是几个整型变量,它们占用 O(1) 的空间。
综上所述,总的空间复杂度是 O(log n),主要由排序算法的空间复杂度决定。
五、总结知识点
-
类定义:定义了一个名为
Solution
的公共类,这是 Java 中的基本面向对象编程结构。 -
方法定义:定义了一个公共方法
findMinDifference
和一个私有辅助方法convertToMinutes
,分别用于查找最小时间差和将时间字符串转换为分钟数。 -
接口和泛型:使用了
List
接口和泛型<String>
来定义方法参数timePoints
,表明这是一个字符串列表。 -
异常处理:虽然没有显式地捕获异常,但
Integer.parseInt
方法可能会抛出NumberFormatException
,通常在实际应用中应该对此进行异常处理。 -
字符串操作:使用了
String.split
方法来分割字符串,并使用String[]
数组来存储分割后的结果。 -
数学运算:执行了基本的算术运算,如乘法、加法和减法,用于时间转换和差值计算。
-
逻辑判断:使用了
if
语句来检查时间点数量是否超过一天中的分钟数,从而直接返回 0。 -
排序:使用了
Collections.sort
方法来对时间点列表进行排序,并自定义了一个比较器来根据时间转换为分钟数进行排序。 -
循环遍历:使用
for
循环遍历列表中的时间点,并计算相邻时间点之间的最小差值。 -
最小值计算:使用
Math.min
方法来计算并更新最小时间差。 -
常量:使用了
Integer.MAX_VALUE
作为初始的最小时间差,确保任何实际的时间差都会小于此值。 -
时间转换:理解了 24 小时制时间与分钟数之间的转换关系,即一天有 1440 分钟。
-
环形时间差:考虑了时间差在一天结束时可能出现的环形情况,即第一个时间点与最后一个时间点之间的差值。
以上就是解决这个问题的详细步骤,希望能够为各位提供启发和帮助。