A Range Module is a module that tracks ranges of numbers. Your task is to design and implement the following interfaces in an efficient manner.
addRange(int left, int right)
Adds the half-open interval
[left, right)
, tracking every real number in that interval. Adding an interval that partially overlaps with currently tracked numbers should add any numbers in the interval
[left, right)
that are not already tracked.
queryRange(int left, int right)
Returns true if and only if every real number in the interval
[left, right)
is currently being tracked.
removeRange(int left, int right)
Stops tracking every real number currently being tracked in the interval
[left, right)
.
Example 1:
addRange(10, 20): null removeRange(14, 16): null queryRange(10, 14): true (Every number in [10, 14) is being tracked) queryRange(13, 15): false (Numbers like 14, 14.03, 14.17 in [13, 15) are not being tracked) queryRange(16, 17): true (The number 16 in [16, 17) is still being tracked, despite the remove operation)
Note:
A half open interval[left, right)
denotes all real numbers
left <= x < right
.
0 < left < right < 10^9
in all calls to
addRange, queryRange, removeRange
.The total number of calls to
addRange
in a single test case is at most
1000
.The total number of calls to
queryRange
in a single test case is at most
5000
.The total number of calls to
removeRange
in a single test case is at most
1000
.
代码实现能力,自己还是比较菜,思路都是一样的,但是写不出来。。。。
package l715;
import java.util.TreeMap;
import java.util.Map.Entry;
/*
* 一般用integer做key就ok
*/
class RangeModule {
TreeMap<Integer, int[]> map = new TreeMap<Integer, int[]>();
public RangeModule() {
}
public void addRange(int left, int right) {
if(map.containsKey(left)) {
int[] cur = map.get(left);
cur[1] = Math.max(cur[1], right); // 相当于已经put进map了
// 通过start就能获取到end啊
Entry<Integer, int[]> higherEntry = map.higherEntry(cur[0]);
while(higherEntry != null) {
if(higherEntry.getKey() > cur[1]) break;
map.remove(higherEntry.getKey());
cur[1] = Math.max(cur[1], higherEntry.getValue()[1]);
higherEntry = map.higherEntry(higherEntry.getKey());
}
} else {
int[] cur = new int[]{left, right};
Entry<Integer, int[]> lowerEntry = map.lowerEntry(cur[0]);
if(lowerEntry != null && lowerEntry.getValue()[1] >= cur[0]) {
map.remove(lowerEntry.getKey());
cur[0] = Math.min(cur[0], lowerEntry.getValue()[0]);
cur[1] = Math.max(cur[1], lowerEntry.getValue()[1]); // 还不能加进map。还要看右边能不能合并
}
Entry<Integer, int[]> higherEntry = map.higherEntry(cur[0]); // 只要是跟后面start有overlap的都要考虑
while(higherEntry != null) {
if(higherEntry.getKey() > cur[1]) break;
map.remove(higherEntry.getKey());
cur[1] = Math.max(cur[1], higherEntry.getValue()[1]);
higherEntry = map.higherEntry(higherEntry.getKey());
}
map.put(cur[0], cur);
}
}
public boolean queryRange(int left, int right) {
Entry<Integer, int[]> floorEntry = map.floorEntry(left);
return floorEntry != null && floorEntry.getValue()[1] >= right;
}
// add 应该也可以仿照remove 不用if直接写
public void removeRange(int left, int right) {
// 左
Entry<Integer, int[]> floorEntry = map.floorEntry(left);
if(floorEntry != null) {
if(floorEntry.getValue()[1] > right)
map.put(right, new int[]{right, floorEntry.getValue()[1]});
floorEntry.getValue()[1] = Math.min(floorEntry.getValue()[1], left); // 一定有
}
// 右
Entry<Integer, int[]> higherEntry = map.higherEntry(left);
int[] cur = higherEntry==null ? null : higherEntry.getValue();
while(cur != null) {
if(cur[0] >= right) break;
map.remove(cur[0]);
if(cur[1] >= right) {
cur[0] = right;
map.put(cur[0], cur);
break;
} else {
higherEntry = map.higherEntry(higherEntry.getKey());
cur = higherEntry==null ? null : higherEntry.getValue();
}
}
}
}
/**
* 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);
*/