给定时间段内重叠间隔的最大范围

问题描述

问题陈述

输入:每30分钟设置间隔(开始时间和结束时间)和每个元素的强度。

例如:

{00:00,01:30,5}

{01:00,02:30,10}

{00:30,02:30,2}

{01:00,04:00,3}

输出:最长30分钟重叠时间和重叠元素的强度总和。

对于上述输入,输出应为01:00-01:30且强度-20(此处的强度为直接总和,因为所有元素都完全参与了最大重叠30分钟,它可能会根据其中的参与时间而有所不同最大间隔)。

用简单的话来说,应该找到最大重叠的30分钟,以及在那个参与元素期间的附加强度。

可能看到不同的线程在回答最大重叠点和间隔,但是找不到上述解决方案。

任何建议都会有所帮助!

解决方法

算法如下:

  1. 定义起点(所有起点的最小值)和终点(所有终点的最大值)点以找到范围
  2. 将范围分成30分钟的子间隔
  3. 计算每个子间隔的总强度
  4. 查找具有最大计算强度的子间隔。

使用Java 8 Stream API和自定义类的实现示例(为方便起见,在几分钟内实现了起点和终点,而没有为简短起见就解析“ HH:MM”字符串)如下:

public class IntervalStrength {
    private final int start; // inclusive
    private final int end;   // exclusive
    private final int strength;
        
    public IntervalStrength(int start,int end,int strength) {
        this.start = start;
        this.end = end;
        this.strength = strength;
    }
        
    public int getStart() { return start; }
    public int getEnd() { return end; }
    public int getStrength() { return strength; }
        
    public String toString() {
        return String.format("[%02d:%02d,%02d:%02d] - %d",start / 60,start % 60,end / 60,end % 60,strength);
    }
}
import java.util.*;
import java.util.stream.*;

public class Main {
    private static final int HALF_HOUR = 30;
    public static void main(String args[]) {
        List<IntervalStrength> data = Arrays.asList(
            new IntervalStrength(0,90,5),new IntervalStrength(60,150,10),new IntervalStrength(30,2),240,3)
        );
        int start = data.stream().mapToInt(IntervalStrength::getStart).min().getAsInt();
        int end = data.stream().mapToInt(IntervalStrength::getEnd).max().getAsInt();
        System.out.println(start + "," + end);
        
        IntervalStrength strongest = IntStream
            .iterate(start,t -> t < end - HALF_HOUR,t -> t + HALF_HOUR)
            .mapToObj(t -> new IntervalStrength(  // create sub-interval
                    t,t + HALF_HOUR,// start and end of sub-interval
                    data.stream()     // find overlapping
                        .filter(d -> d.getStart() <= t && d.getEnd() >= t + HALF_HOUR)
                        .mapToInt(IntervalStrength::getStrength)
                        .sum()  // calculate sum of strengths
            ))
            // find max strength of sub-interval
            .max(Comparator.comparingInt(IntervalStrength::getStrength))
            .get();  // retrieve sub-interval
                 
        System.out.println(strongest);
        
    }
}

输出:

0,240
[01:00,01:30] - 20

“无流”实现可能如下:

public static IntervalStrength findSubintervalMaxStrength(List<IntervalStrength> data) {
    int start = Integer.MAX_VALUE,end = Integer.MIN_VALUE;
        
    for (IntervalStrength interval : data) {
        if (interval.getStart() < start) start = interval.getStart();
        if (interval.getEnd() > end) end = interval.getEnd();
    }
        
    System.out.println(start + "," + end);
        
    int maxStrength = 0;
    int maxIntervalStart = start;
    for (int t = start; t <= end - HALF_HOUR; t += HALF_HOUR) {
        int subintervalStrength = 0;
        for (IntervalStrength interval : data) {
            if (interval.getStart() <= t && interval.getEnd() >= t + HALF_HOUR) {
                subintervalStrength += interval.getStrength();
            }
        }
        if (maxStrength < subintervalStrength) {
            maxStrength = subintervalStrength;
            maxIntervalStart = t;
        }
    }
    return new IntervalStrength(maxIntervalStart,maxIntervalStart + HALF_HOUR,maxStrength);
}