当前位置:   article > 正文

《剑指 Offer》专项突破版 - 面试题 35 : 最小时间差(两种方法 + C++ 实现)

《剑指 Offer》专项突破版 - 面试题 35 : 最小时间差(两种方法 + C++ 实现)

目录

前言

一、排序

二、数组


 


前言

题目链接LCR 035. 最小时间差 - 力扣(LeetCode)

题目

给定一组范围在 00:00 至 23:59 的时间,求任意两个时间之间的最小时间差(以分钟数表示)。例如,输入数组 ["23:50", "23:59", "00:00"],"23:59" 和 "00:00" 之间只有 1 分钟的间隔,是最小的时间差。

分析

这个题目最直观的解法是求出任意两个时间的间隔,然后比较得出最小的时间差。如果输入n个时间,那么这种蛮力法需要 O(n^2) 的时间。


一、排序

上述解法的一个优化方法是把 n 个时间排序。排序之后只需要计算两两相邻的时间之间的间隔,这样就只需要计算 O(n) 个时间差。由于对 n 个时间进行排序通常需要 O(nlogn) 的时间,因此这种优化算法的总体时间复杂度是 O(nlogn)。

这里有一个特殊情况值得注意。如果把输入的时间数组 ["23:50", "23:59", "00:00"] 排序,就可以得到 ["00:00", "23:50", "23:59"]。时间 00:00 和 23:50 之间的间隔是 1430 分钟,而 23:50 和 23:59 之间的间隔是 9 分钟。由于排序之后的第 1 个 00:00 也可能是第 2 天的 00:00,它和前一天的 23:59 之间的间隔只有 1 分钟。也就是说,在计算最小时间差时,需要把排序之后的第 1 个时间当作第 2 天的时间(即加上 24 小时)与最后一个时间之间的间隔也考虑进去

  1. class Solution {
  2. public:
  3.    int findMinDifference(vector<string>& timePoints) {
  4.        if (timePoints.size() > 24 * 60)  // 说明存在相同的时间点
  5.            return 0;
  6.        sort(timePoints.begin(), timePoints.end());
  7.        int minDiff = INT_MAX;
  8.        int prevMinute = stoi(timePoints[0].substr(0, 2)) * 60 + stoi(timePoints[0].substr(3));
  9.        int tmp = prevMinute;
  10.        for (size_t i = 1; i < timePoints.size(); ++i)
  11.       {
  12.            int curMinute = stoi(timePoints[i].substr(0, 2)) * 60 + stoi(timePoints[i].substr(3));
  13.            if (curMinute - prevMinute < minDiff)
  14.                minDiff = curMinute - prevMinute;
  15.            prevMinute = curMinute;
  16.       }
  17.        // 特殊情况
  18.        if (tmp + 24 * 60 - prevMinute < minDiff)
  19.            minDiff = tmp + 24 * 60 - prevMinute;
  20.        return minDiff;
  21.   }
  22. };

 


二、数组

接着思考如何做进一步优化。前面的算法主要将时间花在排序上面,那么排序是否可以避免?排序是为了计算相邻的两个时间的节点,所以用一个表示时间的数组也可以达到这个目的。

一天有 24 小时,即 1440 分钟。如果用一个长度为 1440 的数组表示一天的时间,那么数组下标为 0 的位置对应时间 00:00,下标为 1 的位置对应时间 00:01,以此类推,下标为 1439 的位置对应 23:59。数组中的每个元素是 true 或 false 的标识,表示对应的时间是否存在于输入的时间数组中

有了这个辅助数组,就只需要从头到尾扫描一遍,相邻的两个为 true 的值表示对应的两个时间在输入数组中是相邻的。例如,输入时间数组 ["23:50", "23:59", "00:00"],数组中只有下标为 0、1430 和 1439 这 3 个位置的值为 true,其他位置的值都是 false。

由于数组的下标对应的是时间,因此两个时间之间的时间差就是它们在数组中对应的下标之差。23:50 和 23:59 之间相隔 9 分钟,它们在数组中的下标之差也是 9。

  1. class Solution {
  2. public:
  3.    int findMinDifference(vector<string>& timePoints) {
  4.        if (timePoints.size() > 1440)
  5.            return 0;
  6.        
  7.        vector<bool> minuteFlags(1440, false);
  8.        for (const string& t : timePoints)
  9.       {
  10.            int minute = stoi(t.substr(0, 2)) * 60 + stoi(t.substr(3));
  11.            if (minuteFlags[minute])
  12.                return 0;
  13.            
  14.            minuteFlags[minute] = true;
  15.       }
  16.        int minDiff = INT_MAX;
  17.        int prevMinute = -1;
  18.        int firstMinute = INT_MAX;
  19.        int lastMinute = -1;
  20.        for (int i = 0; i < 1440; ++i)
  21.       {
  22.            if (minuteFlags[i])
  23.           {
  24.                if (prevMinute >= 0)
  25.               {
  26.                    if (i - prevMinute < minDiff)
  27.                        minDiff = i - prevMinute;
  28.               }
  29.                prevMinute = i;
  30.                if (i < firstMinute)
  31.                    firstMinute = i;
  32.                
  33.                if (i > lastMinute)
  34.                    lastMinute = i;
  35.           }
  36.       }
  37.        // 特殊情况
  38.        if (firstMinute + 1440 - lastMinute < minDiff)
  39.            minDiff = firstMinute + 1440 - lastMinute;
  40.        
  41.        return minDiff;
  42.   }
  43. };

该算法的时间复杂度是 O(n),空间复杂度是 O(1)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/blog/article/detail/75349
推荐阅读
相关标签
  

闽ICP备14008679号