1. 程式人生 > >[LeetCode] Minimum Time Difference 最短時間差

[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:

  1. The number of time points in the given list is at least 2 and won't exceed 20000.
  2. 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);
    }
};

參考資料: