CS-Wiki CS-Wiki
Home
知识体系总览
  • 数据结构与算法
  • 计算机网络
  • 操作系统
  • MySQL
  • Redis
  • 设计模式
  • Java 基础
  • Java 集合
  • Java 并发
  • Java 虚拟机
  • Spring
  • Kafka
  • 校招扫盲
  • 项目推荐
  • 唠唠嗑儿
  • 读书笔记
归档
GitHub (opens new window)
Home
知识体系总览
  • 数据结构与算法
  • 计算机网络
  • 操作系统
  • MySQL
  • Redis
  • 设计模式
  • Java 基础
  • Java 集合
  • Java 并发
  • Java 虚拟机
  • Spring
  • Kafka
  • 校招扫盲
  • 项目推荐
  • 唠唠嗑儿
  • 读书笔记
归档
GitHub (opens new window)
  • 刷题模板汇总
  • 一些刷题小技巧
  • 整数 and 位运算

  • 数组

  • 链表

  • 哈希表

    • 哈希表理论基础
    • 剑指 Offer 50 - 第一个只出现一次的字符
    • 验证外星语词典
    • 有效的字母异位词
    • 字母异位词分组
    • 单词长度的最大乘积
    • 两个数组的交集
    • 多个数组求交集
    • 赎金信
    • 快乐数
    • 两数之和
    • 四数相加 II
    • 最小时间差
      • 📃 题目描述
      • 🔔 解题思路
      • 💥 复杂度分析
    • 缺失的第一个正数
    • 最长连续序列
    • 剑指 Offer 03 - 数组中重复的数字
    • 利用哈希表设计高级结构

  • 字符串

  • 栈

  • 队列

  • 二叉树

  • 前缀树

  • 二分查找

  • 双指针法

  • 区间求和问题

  • 排序

  • 回溯算法

  • 贪心算法

  • 动态规划

  • 图

  • 数学

  • 自动机

  • 海量数据和空间限制

  • 05-数据结构与算法
  • 哈希表
小牛肉
2022-04-14
目录

最小时间差

# 📃 题目描述

题目链接:

  • 剑指 Offer II 035. 最小时间差 - 力扣(LeetCode) (leetcode-cn.com) (opens new window)
  • 539. 最小时间差 - 力扣(LeetCode) (leetcode-cn.com) (opens new window)

# 🔔 解题思路

这个题目最直观的解法是求出任意两个时间的间隔,然后比较得出最小的时间差。如果输入 n 个时间,那么需要计算每个时间与另外n-1个时间的间隔,这种蛮力法需要O(n2)的时间。

上述解法的一个优化方法是把 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 小时)与最后一个时间之间的间隔也考虑进去。

再举个例子

比如 01:00(t1) 和 23:00(t2):

  • 情况 1:如果这俩是同一天,那么相差 22 个小时(这种情况肯定需要考虑的,没得说)
  • 情况 2:如果 t1 在第二天,t2 在第一天,那么 t2 再经过 2 个小时就能到 t1 时间(这种情况需要考虑)
  • 情况 3:如果 t1 在第一天,t2 在第二天,那么 t1 还需要 23 + 23 = 46 个小时才能到达 t2(这种情况显然不用考虑了)

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

一天有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。

由于数组的下标对应的是时间,因此两个时间之间的时间差就是它们在数组中对应的下标之差

class Solution {
    public int findMinDifference(List<String> timePoints) {
        boolean[] times = new boolean[1440];
        for (String timePoint : timePoints) {
            int minutes = transfer(timePoint);
            // 如果 times[minutes] 已经置为 true, 说明出现了两个一样的时间,直接返回 0 就行了
            if (times[minutes] == true) {
                return 0;
            }
            times[minutes] = true;
        }

        int minLen = times.length - 1;
        // 这个字段用来计算第 1 种情况(在同一天),两个连续时间 当天 的时间差
        int pre = -1;
        // 这两个字段是用来计算第 2 种情况的(不在同一天),第一天的时间要尽可能大,第二天的时间要尽可能小
        int first = -1; // 第一天
        int last = times.length - 1; // 第二天
        for (int i = 0; i < times.length; i ++) {
            if (times[i] == true) {
                if (pre != -1) {
                    minLen = Math.min(minLen, i - pre);
                }
                
                pre = i;
                // 第一天时间尽可能大
                first = Math.max(first, i);
                // 第二天时间尽可能小
                last = Math.min(last, i);
            }
        }

        return Math.min(minLen, last + times.length - first);
    }

    // hour -> minutes
    private int transfer(String timePoint) {
        String[] item = timePoint.split(":");
        return Integer.parseInt(item[0]) * 60 + Integer.parseInt(item[1]);
    }
}

# 💥 复杂度分析

  • 空间复杂度:O(N)
  • 时间复杂度:O(N)

🎁 公众号

各位小伙伴大家好呀,叫我小牛肉就行,目前在读东南大学硕士,上方扫码关注公众号「飞天小牛肉」,与你分享我的成长历程与技术感悟~

帮助小牛肉改善此页面 (opens new window)
Last Updated: 2023/02/16, 11:27:10
四数相加 II
缺失的第一个正数

← 四数相加 II 缺失的第一个正数→

最近更新
01
关于编程满天星
02
让我来告诉你 Java 程序员是怎么一步一步从入行到被裁的
06-08
03
Vision Pro,未来已来
06-06
更多文章>
Theme by Vdoing | Copyright © 2019-2023 飞天小牛肉 | 皖ICP备2022008966号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式