leetcode
leetcode 1951 ~ 2000
统计区间中的整数数目

统计区间中的整数数目

难度:

标签:

题目描述

代码结果

运行时间: 416 ms, 内存: 57.6 MB


/*
题目思路:
1. 使用集合存储所有区间并保证无重叠。
2. 新增区间时,利用流来过滤和合并重叠的区间。
3. 计算整数个数时,通过流计算所有区间的总长度。
*/
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class CountIntervalsStream {
    private List<int[]> intervals;

    public CountIntervalsStream() {
        intervals = new ArrayList<>();
    }

    public void add(int left, int right) {
        List<int[]> mergedIntervals = intervals.stream()
            .filter(interval -> interval[1] < left || interval[0] > right)
            .collect(Collectors.toList());

        int[] newInterval = {left, right};
        for (int[] interval : intervals) {
            if (interval[1] >= left && interval[0] <= right) {
                newInterval[0] = Math.min(newInterval[0], interval[0]);
                newInterval[1] = Math.max(newInterval[1], interval[1]);
            }
        }

        mergedIntervals.add(newInterval);
        intervals = mergedIntervals;
    }

    public int count() {
        return intervals.stream().mapToInt(interval -> interval[1] - interval[0] + 1).sum();
    }
}

解释

方法:

题解采用了双向链表来维护区间集合,每个节点代表一个区间。每次添加新区间时,会尝试与现有区间合并以避免重叠,并维护一个计数器cnt来统计所有涵盖的整数数量。具体操作包括:1. 如果新区间在所有现有区间的右边,则直接添加,并更新计数器。2. 如果新区间和现有区间有重叠,则进行合并,并适当地更新计数器以反映合并后的区间的变化。3. 使用双向链表可以方便地插入和删除节点,同时更新前后节点的链接。

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
如何处理新添加的区间完全嵌套在现有区间中的情况,例如添加[4,5]到已有的[1,10]区间?
如果新添加的区间完全嵌套在现有区间中,例如添加[4,5]到已有的[1,10]区间,实际上不需要对现有区间进行任何修改,也不影响整体的整数数目。在题解的算法中,当寻找到一个现有区间,该区间的左端点小于或等于新增区间的左端点,并且其右端点大于或等于新增区间的右端点时,就可以确定新区间已被现有区间完全包含,因此无需进行插入或计数器更新。这种情况在题解中没有直接体现,可能需要增加逻辑来处理这种特殊情况,避免不必要的合并或区间更新操作。
🦆
在更新现有区间时,如果新增区间导致多个现有区间合并,`update`函数如何确保所有相关区间都被正确处理并合并?
在`update`函数中,通过从当前节点开始向后遍历,检查每个相邻区间是否与新区间有重叠或相邻。如果有,就将这些区间合并到当前节点中,并更新计数器来反映合并后的整数数目的变化。该函数会减掉所有被合并区间的整数数目,并添加新的合并后的区间的整数数目。遍历继续直到找到一个区间的左端点大于新区间的右端点,确保所有重叠或相邻的区间都被合并。这种方法确保了合并操作的完整性并防止了区间的遗漏。
🦆
在`add`方法中,如果`left`值比`self.tail.prev.right`大,直接插入新区间,但是如果left值恰好是`self.tail.prev.right+1`,是否应该合并区间而不是新增?
是的,如果新区间的左端点`left`恰好等于最后一个区间的右端点加一(`self.tail.prev.right + 1`),则应该将这两个区间合并,而不是创建一个新的区间。这种情况在题解算法中未明确处理,需要修改逻辑以检测这种边界条件并进行合并,从而维护区间的连续性和减少不必要的区间分割。
🦆
当通过`update`方法合并区间时,为什么要从当前节点开始向后遍历,而不是从头开始或者使用其他优化策略?
从当前节点开始向后遍历的原因是,新区间与当前节点已经有了重叠,表明合并应该从此处开始。从头开始遍历虽然可以处理所有情况,但效率较低,因为它不利用到当前位置的信息。对于优化策略,可以考虑使用平衡树(如红黑树)或区间树,这些数据结构可以更高效地处理区间的插入、删除和合并,尤其是在处理大量区间操作时可以显著提高效率。

相关问题