Data Stream as Disjoint Intervals

本文介绍了一种使用Java TreeSet来管理区间的方法,并实现了一个名为SummaryRanges的类。该类能够添加数值并返回所有已添加数值的连续区间。通过自定义比较器确保区间按起始值排序,同时实现了区间合并。

第一次用TreeSet。。。

要懂得用这种结构

/**
 * Definition for an interval.
 * public class Interval {
 *     int start;
 *     int end;
 *     Interval() { start = 0; end = 0; }
 *     Interval(int s, int e) { start = s; end = e; }
 * }
 */
public class SummaryRanges {
TreeSet<Interval> set;
    /** Initialize your data structure here. */
    public SummaryRanges() {
        set = new TreeSet<>(new Comparator<Interval>(){
            @Override
            public int compare(Interval a, Interval b){
                return a.start - b.start;
            }
        });
    }
    
    public void addNum(int val) {
        Interval temp = new Interval(val, val);
        Interval low = set.floor(temp);
        if (low != null) {
            if (low.end >= val) {
                return;
            } else if (low.end + 1 == val) {
                temp.start = low.start;
                set.remove(low);
            }
        }
        Interval high = set.higher(temp);
        if (high != null) {
            if (temp.end + 1 == high.start) {
                temp.end = high.end;
                set.remove(high);
            }
        }
        set.add(temp);
    }
    
    public List<Interval> getIntervals() {
        Iterator<Interval> it = set.iterator();
        List<Interval> list = new LinkedList<>();
        while (it.hasNext()) {
            list.add(it.next());
        }
        return list;
    }
}

/**
 * Your SummaryRanges object will be instantiated and called as such:
 * SummaryRanges obj = new SummaryRanges();
 * obj.addNum(val);
 * List<Interval> param_2 = obj.getIntervals();
 */


### 原理 Disjoint-set 数据结构,也称为并查集(Union-Find),是一种用于管理一组不相交集合的数据结构。它支持两种主要操作: 1. **Find**:确定某个元素属于哪个集合。 2. **Union**:将两个集合合并为一个集合。 在实现上,通常使用树结构来表示每个集合,其中每个节点指向其父节点,根节点作为该集合的代表元素。为了提高效率,常用的优化技术包括路径压缩和按秩合并: - **路径压缩**:在查找过程中,将查找路径上的所有节点直接连接到根节点,从而减少后续查找的时间复杂度。 - **按秩合并**:在合并两个集合时,总是将较小的树连接到较大的树上,以保持树的高度尽可能小。 这些优化使得并查集的操作接近于常数时间复杂度[^4]。 ### 实现 #### 基本实现 基本实现使用一个数组来存储每个元素的父节点信息。初始化时,每个元素的父节点是它自己。查找操作通过递归或迭代的方式找到根节点,而合并操作则需要先找到各自的根节点,然后将其中一个根节点连接到另一个根节点上。 ```python class DisjointSet: def __init__(self, n): self.parent = list(range(n)) def find(self, x): if self.parent[x] != x: self.parent[x] = self.find(self.parent[x]) return self.parent[x] def union(self, x, y): rootX = self.find(x) rootY = self.find(y) if rootX != rootY: self.parent[rootY] = rootX ``` #### 路径压缩与按秩合并 结合路径压缩和按秩合并的实现可以显著提高性能。路径压缩通过在查找时调整节点的父指针来减少未来的查找时间,而按秩合并通过维护树的高度来防止树变得过高。 ```python class DisjointSetOptimized: def __init__(self, n): self.parent = list(range(n)) self.rank = [0] * n def find(self, x): if self.parent[x] != x: self.parent[x] = self.find(self.parent[x]) return self.parent[x] def union(self, x, y): rootX = self.find(x) rootY = self.find(y) if rootX == rootY: return if self.rank[rootX] > self.rank[rootY]: self.parent[rootY] = rootX else: self.parent[rootX] = rootY if self.rank[rootX] == self.rank[rootY]: self.rank[rootY] += 1 ``` ### 应用场景 Disjoint-set 数据结构广泛应用于以下领域: - **图算法**:例如 Kruskal 算法中的最小生成树问题,用于检测环路以及判断两个顶点是否属于同一个连通分量。 - **动态连通性问题**:如网络连接、社交网络分析等场景中,用于快速判断两个节点是否连通。 - **图像处理**:用于图像分割中的区域标记,识别图像中的不同对象。 - **编译器设计**:在类型推断和变量统一中,用于高效地处理等价类问题。 这些应用场景得益于并查集高效的查找和合并操作,使其能够在大规模数据处理中表现出色[^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值