You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于数组表示的时间槽列表计算空闲时段(NOR操作)?

解决时间槽的NOR操作:找出未被占用的空闲时段

嘿,这个需求其实挺常见的,核心就是把时间槽处理成容易计算的格式,然后按顺序排查空隙就行。我给你理清楚步骤,再附上可运行的代码示例:

核心思路

  • 先把所有时间(包括总区间的起止和每个槽的起止)转换成总分钟数,这样加减计算就完全不用管小时和分钟的换算问题,特别省心。
  • 对所有时间槽按开始时间排序,如果原列表是无序的,这一步必须做,不然没法连续检查相邻槽的空隙。
  • 从总区间的开始时间出发,依次对比当前槽的开始时间和上一个区间的结束时间:如果前者大于后者,中间的就是空闲时段。
  • 别忘了处理总区间的「开头空隙」(第一个槽开始晚于总区间起点)和「结尾空隙」(最后一个槽结束早于总区间终点)。

代码实现(Java示例)

先写个工具方法把{小时,分钟}数组转成总分钟数:

private static int convertToMinutes(int[] time) {
    return time[0] * 60 + time[1];
}

然后写核心方法,输入总区间的起止、时间槽列表,返回空闲时段列表:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

public class TimeSlotNOR {
    public static List<int[][]> findFreeSlots(int[] totalStart, int[] totalEnd, List<int[][]> occupiedSlots) {
        List<int[][]> freeSlots = new ArrayList<>();
        
        // 1. 把所有时间转成分钟数
        int totalStartMin = convertToMinutes(totalStart);
        int totalEndMin = convertToMinutes(totalEnd);
        
        // 2. 对占用的时间槽按开始时间排序
        occupiedSlots.sort(Comparator.comparingInt(slot -> convertToMinutes(slot[0])));
        
        // 3. 初始化上一个结束时间为总区间的开始
        int lastEndMin = totalStartMin;
        
        for (int[][] slot : occupiedSlots) {
            int slotStartMin = convertToMinutes(slot[0]);
            int slotEndMin = convertToMinutes(slot[1]);
            
            // 如果当前槽的开始时间晚于上一个结束时间,说明有空隙
            if (slotStartMin > lastEndMin) {
                // 把分钟数转回到{小时,分钟}格式
                int[] freeStart = {lastEndMin / 60, lastEndMin % 60};
                int[] freeEnd = {slotStartMin / 60, slotStartMin % 60};
                freeSlots.add(new int[][]{freeStart, freeEnd});
            }
            
            // 更新上一个结束时间为当前槽的结束时间(取较大值,防止重叠槽的情况)
            lastEndMin = Math.max(lastEndMin, slotEndMin);
        }
        
        // 4. 处理总区间结尾的空隙
        if (lastEndMin < totalEndMin) {
            int[] freeStart = {lastEndMin / 60, lastEndMin % 60};
            int[] freeEnd = {totalEndMin / 60, totalEndMin % 60};
            freeSlots.add(new int[][]{freeStart, freeEnd});
        }
        
        return freeSlots;
    }
    
    private static int convertToMinutes(int[] time) {
        return time[0] * 60 + time[1];
    }
    
    // 测试示例
    public static void main(String[] args) {
        // 总区间:9:00-17:00
        int[] totalStart = {9, 0};
        int[] totalEnd = {17, 0};
        
        // 占用的时间槽:09:00-14:00 和 16:00-17:00
        List<int[][]> occupiedSlots = new ArrayList<>();
        occupiedSlots.add(new int[][]{{9, 0}, {14, 0}});
        occupiedSlots.add(new int[][]{{16, 0}, {17, 0}});
        
        List<int[][]> freeSlots = findFreeSlots(totalStart, totalEnd, occupiedSlots);
        
        // 打印结果
        for (int[][] slot : freeSlots) {
            System.out.printf("%d:%02d-%d:%02d%n", 
                slot[0][0], slot[0][1], slot[1][0], slot[1][1]);
        }
        // 输出:14:00-16:00,和你的示例一致
    }
}

关键细节说明

  • 时间转换:把{小时,分钟}转成总分钟数是核心,避免了处理跨小时的计算错误(比如13:59到14:01,直接用分钟数差就是2,非常直观)。
  • 排序处理:如果原时间槽列表是乱序的(比如先给16:00-17:00,再给9:00-14:00),排序后才能正确遍历检查空隙。
  • 重叠槽处理:用Math.max(lastEndMin, slotEndMin)更新上一个结束时间,就算有重叠的占用槽(比如一个槽是10:00-15:00,另一个是13:00-16:00),也能正确合并成一个连续的占用区间,不会出错。
  • 边界情况:比如所有时间槽都覆盖了总区间,那返回的空闲列表就是空的;如果总区间里没有任何占用槽,就返回整个总区间。

内容的提问来源于stack exchange,提问作者nuggetbram

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:20:07