区间合并算法学习笔记

182 阅读2分钟

floorEntry(K key) 是 TreeMap 类中的一个方法,用于返回 TreeMap 中键小于等于给定键的最大键值对(Entry)。如果不存在这样的键值对,则返回 null。下面是 floorEntry(K key) 方法的示例用法:

public class FloorEntryExample {
    public static void main(String[] args) {
        TreeMap<Integer, String> treeMap = new TreeMap<>();
        treeMap.put(1, "One");
        treeMap.put(3, "Three");
        treeMap.put(5, "Five");

        // 使用 floorEntry() 方法获取键小于等于 4 的最大键值对
        Map.Entry<Integer, String> floorEntry = treeMap.floorEntry(4);
        if (floorEntry != null) {
            System.out.println("Key: " + floorEntry.getKey() + ", Value: " + floorEntry.getValue());
        } else {
            System.out.println("No floor entry found.");
        }
    }
}

在上述示例中,我们创建了一个 TreeMap,并插入了几个键值对。然后,我们使用 floorEntry() 方法查找键小于等于 4 的最大键值对。根据示例数据,键小于等于 4 的最大键值对是键为 3 的键值对。因此,输出结果为:

Key: 3, Value: Three

floorEntry(K key) 方法返回的是一个 Map.Entry 对象,可以通过 getKey()getValue() 方法获取键和值。

利用这个特性,可以将TreeMap当作是一个坐标轴,用作区间合并,以下是算法实现:

private final TreeMap<Integer, Integer> map = new TreeMap<>();
public void mergeOfIntervals(int l2, int r2) {
    for (Map.Entry<Integer, Integer> entry = map.floorEntry(r2); entry != null && entry.getValue() >= l2; entry = map.floorEntry(r2)) {
        int l1 = entry.getKey();
        int r1 = entry.getValue();
        l2 = Math.min(l2, l1);
        r2 = Math.max(r2, r1);
        map.remove(l1);
    }
    map.put(l2, r2);
}

假设两个区间为(l1,r1)(l2,r2),那么这两个区间的关系有以下三种:

存在交集

image.png

一个区间为另一个区间子集

image.png

两个区间没有交集

image.png

调用floorEntry(K key)方法,传入新区间右边界r2,获取最大的、小于r2的旧区间左边界l1,当l2大于r1时两个区间没有交集,此时直接存入map

map.put(l2, r2);

当两个区间存在交集时,记录新边界值,取

l2 = Math.min(l2, l1);
r2 = Math.max(r2, r1);

并且把旧区间删去

map.remove(l1);

由于新区间可能与原有区间再次重合,所以需要循环操作,循环的条件为

entry != null && entry.getValue() >= l2;

其中的entry.getValue()为旧边界l1,因r2 > l1,故只需l2 > l1两区间便没有交集,即为循环终点。