我知道这是一个定义明确的问题,通常可以通过间隔树来解决。我找到了解决方法here。但是我对此仍有一些疑问。
方法I:使用间隔树,时间复杂度O(logN + K),其中N是间隔的总数,K是重叠间隔的数量。
(1)我们如何选择中心点? Wiki并未真正提及选择,而link则提及“此树中的分区值也基于中位数,但中值取自所有间隔的2N个端点。”根据我的理解,我们选择中心点以使间隔树“平衡”。但是,如果是这种情况,这是否意味着间隔树无法自平衡(因为它取决于中心点的选择)?
方法II:构建哈希图。时间复杂度O(1)
我觉得此方法使用相交间隔作为键,并使用与该相交对应的间隔列表作为值。例如,给定间隔[1,3]和[2,4],哈希映射的键将是[1,2],[2,3],[3,4],值将是[1、2 ] => {[1,3]},[2,3] => {[1,3],[2,4]},[3,4] => {[2,4]}。
我的问题是
(1)在上面的示例中,如果我们查询number = 2怎么办,那么有两个包含2的交集间隔,我们如何知道要返回的值?
(2)如果一个交集间隔类似于[2,2],我们是否应该将其用作单独的键?我发现很难分析两种情况。一个是交点的开始=结束,另一个是输入间隔包含两个相同的间隔,例如[1,2]和[1,2]
任何帮助将不胜感激!
如果需要,下面是我对解决方案2的代码
Map<Interval, List<Interval>> map;
private void init(List<Interval> input) {
// step 1 sort input
// step 2:
PriorityQueue<Interval> minHeap = new PriorityQueue<>(new Comparator<Interval>() {
@Override
public int compare(Interval o1, Interval o2) {
return o1.end - o2.end;
}
});
Map<Interval, List<Interval>> map = new HashMap<>();
int start = 0; // init should be redundant
for (int i = 0; i < input.size(); i++) {
Interval cur = input.get(i);
if (minHeap.isEmpty()) {
start = input.get(i).start;
minHeap.offer(cur);
} else if (minHeap.peek().end < cur.start) { // [] both start and end are inclusive
List<Interval> values = new ArrayList<>(minHeap);
Interval min = minHeap.poll();
map.put(new Interval(start, min.end), values);
i--;
start = min.end;
} else {
minHeap.offer(cur);
map.put(new Interval(start, cur.start), new ArrayList<>(minHeap));
start = cur.start;
}
}
// pop until the pq is empty
while (!minHeap.isEmpty()) {
List<Interval> values = new ArrayList<>(minHeap);
Interval cur = minHeap.poll();
map.put(new Interval(start, cur.end), values);
}
this.map = map;
}