1
+ // Runtime: 234 ms (Top 86.20%) | Memory: 71.1 MB (Top 79.66%)
1
2
/*
2
3
https://leetcode.com/problems/range-module/
3
-
4
+
4
5
Idea is to use a height balanced tree to save the intervals. Intervals are kept
5
6
according to the start point.
6
7
We search for the position where the given range can lie, then check the previous if it overlaps
7
8
and keep iterating forward while the intervals are overlapping.
8
-
9
- QueryRange:
9
+
10
+ QueryRange:
10
11
We first find the range of values in [left, right). Then for each of the overlapping intervals,
11
12
we subtract the common range. Finally if the entire range is covered, then the range will become zero.
12
13
*/
@@ -17,56 +18,56 @@ class RangeModule {
17
18
// Important to implement for == case, otherwise intervals
18
19
// with same start won't exist
19
20
// return start < b.start || (start == b.start && end < b.end);
20
-
21
+
21
22
// This is the best way to compare since tuple already have ordering implemented for
22
23
// fields
23
24
return tie (start, end) < tie (b.start , b.end );
24
25
}
25
-
26
+
26
27
int start = -1 , end = -1 ;
27
28
Interval (int start, int end): start(start), end(end) {};
28
29
};
29
-
30
+
30
31
set<Interval> intervals;
31
32
public:
32
33
RangeModule () {
33
-
34
+
34
35
}
35
-
36
+
36
37
// TC: Searching O(logn) + O(n) Merging, worst case when current interval covers all, insertion would take O(1)
37
38
// SC: O(1)
38
39
void addRange (int left, int right) {
39
40
Interval interval (left, right);
40
- // Find the position where interval should lie st the next interval's
41
+ // Find the position where interval should lie st the next interval's
41
42
// start >= left
42
43
auto it = intervals.lower_bound (interval);
43
-
44
+
44
45
// check if previous overlaps, move the iterator backwards
45
46
if (!intervals.empty () && it != intervals.begin () && prev (it)->end >= interval.start ) {
46
47
--it;
47
48
interval.start = min (it->start , interval.start );
48
49
}
49
-
50
+
50
51
// merge while intervals overlap
51
52
while (it != intervals.end () && it->start <= interval.end ) {
52
53
interval.end = max (it->end , interval.end );
53
54
intervals.erase (it++);
54
55
}
55
56
intervals.insert (interval);
56
57
}
57
-
58
+
58
59
// TC: Searching O(logn) + O(n) Merging, worst case when current interval covers all
59
60
// SC: O(1)
60
61
bool queryRange (int left, int right) {
61
62
Interval interval (left, right);
62
63
// Range of numbers that needs to be checked
63
64
int range = right - left;
64
- // Find the position where interval should lie st the next interval's
65
+ // Find the position where interval should lie st the next interval's
65
66
// start >= left
66
67
auto it = intervals.lower_bound (interval);
67
-
68
+
68
69
// check if previous interval overlaps the range, previous only
69
- // covers iff the open end > start of current. [prev.start, prev.end) [left, right)
70
+ // covers iff the open end > start of current. [prev.start, prev.end) [left, right)
70
71
if (!intervals.empty () && it != intervals.begin () && prev (it)->end > interval.start ) {
71
72
// remove the common portion
72
73
int common = min (interval.end , prev (it)->end ) - interval.start ;
@@ -81,39 +82,39 @@ class RangeModule {
81
82
// Check if the entire range was covered or not
82
83
return range == 0 ;
83
84
}
84
-
85
+
85
86
// TC: Searching O(logn) + O(n) Merging, worst case when current interval covers all
86
87
// SC: O(1)
87
88
void removeRange (int left, int right) {
88
89
Interval interval (left, right);
89
- // Find the position where interval should lie st the next interval's
90
+ // Find the position where interval should lie st the next interval's
90
91
// start >= left
91
92
auto it = intervals.lower_bound (interval);
92
-
93
+
93
94
// check if previous overlaps, then move the iterator position backwards
94
- if (!intervals.empty () && it != intervals.begin () && prev (it)->end > interval.start )
95
+ if (!intervals.empty () && it != intervals.begin () && prev (it)->end > interval.start )
95
96
--it;
96
-
97
+
97
98
// For each of the overlapping intervals, remove the common portions
98
99
while (it != intervals.end () && it->start < interval.end ) {
99
100
// Start and End of common portion
100
101
int common_start = max (interval.start , it->start );
101
102
int common_end = min (interval.end , it->end );
102
-
103
+
103
104
// only a section of interval overlaps, remove that part
104
105
// an overlapping interval might have to be broken into two non-overlapping parts
105
- // Eg [---------------------) Bigger interval
106
- // [--------) Ongoing interval
107
- // [------) [-----) Original interval broken into left and right parts
108
-
106
+ // Eg [---------------------) Bigger interval
107
+ // [--------) Ongoing interval
108
+ // [------) [-----) Original interval broken into left and right parts
109
+
109
110
// check if there is some range left on the left side
110
- if (it->start < common_start)
111
- intervals.insert (Interval (it->start , common_start));
112
-
111
+ if (it->start < common_start)
112
+ intervals.insert (Interval (it->start , common_start));
113
+
113
114
// check if there is some range left on the right side
114
- if (it->end > common_end)
115
+ if (it->end > common_end)
115
116
intervals.insert (Interval (common_end, it->end ));
116
-
117
+
117
118
// Remove the original interval
118
119
intervals.erase (it++);
119
120
}
@@ -126,4 +127,4 @@ class RangeModule {
126
127
* obj->addRange(left,right);
127
128
* bool param_2 = obj->queryRange(left,right);
128
129
* obj->removeRange(left,right);
129
- */
130
+ */
0 commit comments