LeetCode 715. Range Module
原题链接在这里:https://leetcode.com/problems/range-module/
题目:
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 numbersleft <= x < right
. 0 < left < right < 10^9
in all calls toaddRange, queryRange, removeRange
.- The total number of calls to
addRange
in a single test case is at most1000
. - The total number of calls to
queryRange
in a single test case is at most5000
. - The total number of calls to
removeRange
in a single test case is at most1000
.
题解:
Have a TreeMap to store existing interval, key is start of interval and value is end.
When adding range, get floor key of left, if key exists and its corresponding value >= left, then there is a merge, left = preKey.
get floor key of right, if key exists and it sorrsonding value >= right, then there is another merge, right = tm.get(nextKey).
Add the new range and clear the keys from (left, right].
When querry Range, just check if there is existing interval coverring [left, right].
When removing range, first get floor key of right, if it exists and value > right, then after removing, there is still some range left. Add new range [right, tm.get(nextKey)).
Do the similar to left. But we need to do right first, because we may change map entry value for preKey if we do left first.
e.g. 1 -> 10, we need to remove 3 -> 7, if we do left first, it becomes 1 -> 3 and misses the 7 -> 10.
Then remove keys in range [left, right).
Time Complexity: addRange, O(nlogn). clear takes O(nlogn). queryRange, O(logn). removeRange, O(nlogn).
Space: O(n).
AC Java:
1 class RangeModule { 2 TreeMap<Integer, Integer> tm; 3 4 public RangeModule() { 5 tm = new TreeMap<>(); 6 } 7 8 public void addRange(int left, int right) { 9 if(left >= right){ 10 return; 11 } 12 13 Integer preKey = tm.floorKey(left); 14 if(preKey != null && tm.get(preKey) >= left){ 15 left = preKey; 16 } 17 18 Integer nextKey = tm.floorKey(right); 19 if(nextKey != null && tm.get(nextKey) >= right){ 20 right = tm.get(nextKey); 21 } 22 23 tm.put(left, right); 24 tm.subMap(left, false, right, true).clear(); 25 } 26 27 public boolean queryRange(int left, int right) { 28 Integer preKey = tm.floorKey(left); 29 if(preKey == null){ 30 return false; 31 } 32 33 return tm.get(preKey) >= right; 34 } 35 36 public void removeRange(int left, int right) { 37 if(left >= right){ 38 return; 39 } 40 41 Integer nextKey = tm.floorKey(right); 42 if(nextKey != null && tm.get(nextKey) > right){ 43 tm.put(right, tm.get(nextKey)); 44 } 45 46 Integer preKey = tm.floorKey(left); 47 if(preKey != null && tm.get(preKey) > left){ 48 tm.put(preKey, left); 49 } 50 51 tm.subMap(left, true, right, false).clear(); 52 } 53 } 54 55 /** 56 * Your RangeModule object will be instantiated and called as such: 57 * RangeModule obj = new RangeModule(); 58 * obj.addRange(left,right); 59 * boolean param_2 = obj.queryRange(left,right); 60 * obj.removeRange(left,right); 61 */