剑指offer35:最小时间差

题目:
给定一组范围再00:00至23:59的时间,求任意两个时间之间的最小时间差,例如输入时间数组 [“23:50”,“23:59”,“00:00”],"23:59"和"00:00"之间只有1分钟的间隔,是最小的时间差。
分析:
这道题最简单的做法就是直接第一个和第二个减,第一个和第三个减,第二个和第三个减,如果输入n个时间,则需要比较n(n-1)/2次,时间复杂度为O(n ^2)。
第二种优化的解法就是先排序,然后相邻两两相减,只需要计算O(n)个时间差,由于对n个时间排序需要O(nlogn)的时间,因此该算法总体时间复杂度是O(nlogn)。
还有一种解法可以以空间换时间,将排序步骤省掉,创建一个哈希表,哈希表的键是时间,值是true或false,true代表存在这个时间,false代表不存在这个时间,只需要计算相减相邻值为true的哈希表的键即可无需排序,一天24h折算成时间是1440分钟,用一个长度为1440的数组表示一天的时间,那么下标为0的位置对应的时间是00:00,下标为1的位置对应00:01,以此类推。
有一种特殊情况需要讨论:在计算最小时间差时,需要把排序后的最后一个时间当作第二天的时间(也就是加上24小时)与最后一个时间之间的间隔也考虑进去。例如00:01,00:04,23:59,23:59到第二天00:01只需要2min,第一天23:59到第二天00:04肯定比到00:01时间差就不用算了,所以只需要把最后一个时间当作第二天即可。
代码:

import java.util.List;

public class FindMinDifference {
    public static int findMinDifference(List<String> timepoints){
//        如果输入的时间数组长度比1440还长,说明一定有重复的,因此最小时间差一定是0
        if (timepoints.size() > 1440){
            return 0;
        }
        boolean[] nums = new boolean[1440];
        for(String time: timepoints){
            String t[] = time.split(":");
            int min = Integer.parseInt(t[0])*60 + Integer.parseInt(t[1]);
//            如果存在两个相同的时间,那么最少时间差一定是0
            if (nums[min]){
                return 0;
            }
            nums[min] = true;
        }
        return helper(nums);
    }

    private static int helper(boolean[] nums) {
        int minDiff = nums.length-1;
        int prev = -1;
        int first = nums.length-1;
        int last = -1;
        for (int i = 0; i < nums.length - 1; i++) {
            if (nums[i]){
                if (prev >= 0){
                    minDiff = Math.min(i - prev,minDiff);
                }
                prev = i;
                first = Math.min(i,first);
                last = Math.max(i,last);
            }
        }
        minDiff = Math.min(first+nums.length-last,minDiff);
        return minDiff;
    }
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龙崎流河

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值