leetcode刷题记录-539. 最小时间差利用鸽巢原理优化方法

「这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战

前言

今天主要是学习了鸽巢原理和 sort() 所不知道的特殊用法

题目描述

今天的题目为leetcode上的 539. 最小时间差 难度为 中等

  • 给定一个 24 小时制(小时:分钟 "HH:MM")的时间列表,找出列表中任意两个时间的最小时间差并以分钟数表示。

示例 1:

输入:timePoints = ["23:59","00:00"]
输出:1
复制代码

示例 2:

输入:timePoints = ["00:00","23:59","00:00"]
输出:0
复制代码

提示:

  • 2 <= timePoints.length <= 2 * 104
  • timePoints[i] 格式为 "HH:MM"

题解

可以先将列表的数据转化为具体的数字,通过分析4个字符写一个简单的转化函数getMinutes(t)

const getMinutes = (t){
    return ((t[0].charCodeAt() - '0'.charCodeAt()) * 10 + (t[1].charCodeAt()  
            - '0'.charCodeAt())) * 60 + (t[3].charCodeAt() - '0'.charCodeAt())  
            * 10 + (t[4].charCodeAt() - '0'.charCodeAt())
}
复制代码

这样会更加方便我们之后的运算。

暴力解法

首先这道题有一种很简单的解法,看似时间之间的比较会比较麻烦,但是我们通过上面的方法将时间变为具体的分钟,就可以把所有的时间进行排序,然后通过对比每个相邻的时间之间的间隙,就可以得到相隔最小的时间是多少,这里要注意最小的时间和最大的时间,可能会存在 00:00 和 23:59 这种情况,所有要额外去对比一下首位和末尾。

var findMinDifference = function(timePoints) {
    let arr =[]
    for(o of timePoints){
        arr.push(getMinutes(o)) //用一个新数组保存转化后的分钟
    }
     console.log(arr)
    arr.sort(function(a, b){return a - b})  //排序
    console.log(arr)
    let ans = 1440;
    let oneMinutes = arr[0];
    let preMinutes = oneMinutes;
    for (let i = 1; i < arr.length; ++i) {
        const minutes = arr[i];
        ans = Math.min(ans, minutes - preMinutes); // 相邻时间的时间差
        preMinutes = minutes;
    }
    ans = Math.min(ans, oneMinutes + 1440 - preMinutes); // 首尾时间的时间差
    return ans;
};
复制代码

image.png

利用鸽巢原理进行优化

并且我们还可以运用鸽巢原理来优化我们的代码,鸽巢原理就是:

  • 假如有十个苹果,但是只有九个盒子,那么必然有一个苹果放不下。扩展开来就是假如有 n+1 个元素要放到 n 个集合中,那么必然有一个集合会含有两个元素。

这道题同理,因为时间的分钟最多只有 24×60=1440 种不同的情况,所以当输入的 n 大于这个数字的时候,必然会有两个相同的时间,这时候我们就直接返回 0 就可以了

这样就可以在我们上面的代码前面加一段优化:

const n = timePoints.length; if (n > 1440) { return 0; }
复制代码

优化-直接排序原数组

上述的过程中建立了一个新的数组来存放转化后的分钟,这十分的浪费内存,我们可以直接在原数组上使用sort()方法排序,具体为:

var findMinDifference = function(timePoints) {
     timePoints.sort();
     ...
     ...
};
复制代码

因为sort()默认的排序机制是将元素当做字符串一个一个对比,具体可以见官方Array.prototype.sort() - JavaScript | MDN (mozilla.org) 所以我们就可以不用新建一个数组保存转化后的分钟,直接遍历排序后的原数组,在赋值的时候进行转化就可以了。
接下去附上优化最后的代码:

var findMinDifference = function(timePoints) {
    const n = timePoints.length;
    if (n > 1440) {
        return 0;
    }
    timePoints.sort(); //排序
    let ans = 1440;
    let oneMinutes = getMinutes(timePoints[0]);
    let preMinutes = oneMinutes;
    for (let i = 1; i < n; ++i) {
        const minutes = getMinutes(timePoints[i]);
        ans = Math.min(ans, minutes - preMinutes); // 相邻时间的时间差
        preMinutes = minutes;
    }
    ans = Math.min(ans, oneMinutes + 1440 - preMinutes); // 首尾时间的时间差
    return ans;
};
复制代码

image.png

Guess you like

Origin juejin.im/post/7054562111950684190