715. Range Module
Sep 14, 2021

Basic Idea
基本思路有两个,一个是使用SegmentTree,还有一个是使用TreeMap。
TreeMap Solution
利用TreeMap排序的性质,维持merge interval的操作,在其中存放互不重叠的interval。利用 TreeMap.subMap(left, true, right, false)
来删掉中间overlap的小区间。
SegmentTree Solution
对于SegmentTree我之前的印象一直是需要和总数据量一样大的空间和时间,但事实上并不需要。在query的时候如果当前的node没有child,则说明child的性质和当前的node相同,可以直接返回。只有在更新的时候需要按需求populate 左右node。
class RangeModule {
SegmentTree tree;
public RangeModule() {
this.tree = new SegmentTree(1, (int) 1e9);
}
public void addRange(int left, int right) {
tree.update(left, right - 1, true);
}
public boolean queryRange(int left, int right) {
return tree.query(left, right - 1);
}
public void removeRange(int left, int right) {
tree.update(left, right - 1, false);
}
private static class SegmentTree {
private static class TreeNode {
TreeNode left, right;
int start, end;
boolean tracked;
TreeNode(int start, int end, boolean tracked) {
this.start = start;
this.end = end;
this.tracked = tracked;
}
}
private TreeNode root;
SegmentTree(int left, int right) {
this.root = new TreeNode(left, right, false);
}
boolean query(int left, int right) {
return query(left, right, root);
}
void update(int left, int right, boolean tracked) {
update(left, right, tracked, root);
}
private boolean query(int left, int right, TreeNode node) {
if (node.left == null) {
// 此时该node没有孩子,表示该范围内所有interval状态相同
return node.tracked;
}
int mid = (node.start + node.end) / 2;
boolean ret = true;
if (right <= mid) {
return query(left, right, node.left);
} else if (left > mid) {
return query(left, right, node.right);
} else {
return query(left, mid, node.left) & query(mid + 1, right, node.right);
}
}
private void update(int left, int right, boolean tracked, TreeNode node) {
if (left == node.start && right == node.end) {
node.left = null;
node.right = null;
node.tracked = tracked;
return;
}
int mid = (node.start + node.end) / 2;
// 这里延迟populate左右孩子,状态初始化为和parent相同
if (node.left == null) {
node.left = new TreeNode(node.start, mid, node.tracked);
node.right = new TreeNode(mid + 1, node.end, node.tracked);
}
if (left <= mid) {
update(left, Math.min(right, mid), tracked, node.left);
}
if (right > mid) {
update(Math.max(mid + 1, left), right, tracked, node.right);
}
node.tracked = node.left.tracked & node.right.tracked;
}
}
}
/**
* Your RangeModule object will be instantiated and called as such:
* RangeModule obj = new RangeModule();
* obj.addRange(left,right);
* boolean param_2 = obj.queryRange(left,right);
* obj.removeRange(left,right);
*/
Last updated