[LeetCode] Minimum Time Difference 最短时间差
Given a list of 24-hour clock time points in "Hour:Minutes" format, find the minimum minutes difference between any two time points in the list.
Example 1:
Input: ["23:59","00:00"] Output: 1
Note:
- The number of time points in the given list is at least 2 and won't exceed 20000.
- The input time is legal and ranges from 00:00 to 23:59.
这道题给了我们一系列无序的时间点,让我们求最短的两个时间点之间的差值。那么最简单直接的办法就是给数组排序,这样时间点小的就在前面了,然后我们分别把小时和分钟提取出来,计算差值,注意唯一的特殊情况就是第一个和末尾的时间点进行比较,第一个时间点需要加上24小时再做差值,参见代码如下:
解法一:
class Solution { public: int findMinDifference(vector<string>& timePoints) { int res = INT_MAX, n = timePoints.size(), diff = 0; sort(timePoints.begin(), timePoints.end()); for (int i = 0; i < n; ++i) { string t1 = timePoints[i], t2 = timePoints[(i + 1) % n]; int h1 = (t1[0] - '0') * 10 + t1[1] - '0'; int m1 = (t1[3] - '0') * 10 + t1[4] - '0'; int h2 = (t2[0] - '0') * 10 + t2[1] - '0'; int m2 = (t2[3] - '0') * 10 + t2[4] - '0'; diff = (h2 - h1) * 60 + (m2 - m1); if (i == n - 1) diff += 24 * 60; res = min(res, diff); } return res; } };
下面这种写法跟上面的大体思路一样,写法上略有不同,是在一开始就把小时和分钟数提取出来并计算总分钟数存入一个新数组,然后再对新数组进行排序,再计算两两之差,最后还是要处理首尾之差,参见代码如下:
解法二:
class Solution { public: int findMinDifference(vector<string>& timePoints) { int res = INT_MAX, n = timePoints.size(); vector<int> nums; for (string str : timePoints) { int h = stoi(str.substr(0, 2)), m = stoi(str.substr(3)); nums.push_back(h * 60 + m); } sort(nums.begin(), nums.end()); for (int i = 1; i < n; ++i) { res = min(res, nums[i] - nums[i - 1]); } return min(res, 1440 + nums[0] - nums.back()); } };
上面两种方法的时间复杂度都是O(nlgn),我们来看一种O(n)时间复杂度的方法,由于时间点并不是无穷多个,而是只有1440个,所以我们建立一个大小为1440的数组来标记某个时间点是否出现过,如果之前已经出现过,说明有两个相同的时间点,直接返回0即可;若没有,将当前时间点标记为出现过。我们还需要一些辅助变量,pre表示之前遍历到的时间点,first表示按顺序排的第一个时间点,last表示按顺序排的最后一个时间点,然后我们再遍历这个mask数组,如果当前时间点出现过,再看如果first不为初始值的话,说明pre已经被更新过了,我们用当前时间点减去pre来更新结果res,然后再分别更新first,last,和pre即可,参见代码如下:
解法三:
class Solution { public: int findMinDifference(vector<string>& timePoints) { int res = INT_MAX, pre = 0, first = INT_MAX, last = INT_MIN; vector<int> mask(1440, 0); for (string str : timePoints) { int h = stoi(str.substr(0, 2)), m = stoi(str.substr(3)); if (mask[h * 60 + m] == 1) return 0; mask[h * 60 + m] = 1; } for (int i = 0; i < 1440; ++i) { if (mask[i] == 1) { if (first != INT_MAX) { res = min(res, i - pre); } first = min(first, i); last = max(last, i); pre = i; } } return min(res, 1440 + first - last); } };
参考资料:
https://discuss.leetcode.com/topic/83250/easy-c-solution
https://discuss.leetcode.com/topic/82573/verbose-java-solution-bucket
https://discuss.leetcode.com/topic/82575/java-o-nlog-n-o-n-time-o-1-space-solutions