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
.
解题思路:
解法一:将所有不相交的区间放置到向量中,跟之前的区间的题目Insert Interval和Merge Intervals没有什么不同 。
但是添加区间,删除区间的的时间复杂度就是O(N),查找用二分查找时间复杂度是O(logN),但是超时了;
class RangeModule {
public:
RangeModule() {
}
void addRange(int left, int right)
{
if(intes.empty())
{
intes.push_back({left , right}) ;
return ;
}
auto itb = intes.begin() ;
vector<vector<int>> newintes ;
while(itb != intes.end() && (*itb)[0] <= right)
{
if((*itb)[1] < left)
{
newintes.push_back(*itb) ;
itb++ ;
continue ;
}
left = min((*itb)[0] , left) ;
right = max((*itb)[1] , right) ;
itb++ ;
}
newintes.push_back({left , right}) ;
newintes.insert(newintes.end() , itb , intes.end()) ;
intes = newintes ;
}
bool queryRange(int left, int right)
{
int l = 0 , r = intes.size() ;
while(l < r)
{
int mid = l + (r - l)/2 ;
if(intes[mid][0] <= left && intes[mid][1] >= right) return true ;
else if(intes[mid][1] <= left) l = mid + 1 ;
else if(intes[mid][0] >= right) r = mid ;
else return false ;
}
return false ;
}
void removeRange(int left, int right)
{
vector<vector<int>> newintes ;
auto itb = intes.begin() ;
while(itb != intes.end())
{
if((*itb)[1] <= left)
{
newintes.push_back(*itb) ;
itb++ ;
continue ;
}
if(right <= (*itb)[1])
{
int newleft = right ;
if(left > (*itb)[0]) newintes.push_back({(*itb)[0] , left }) ;
if(newleft < (*itb)[1]) newintes.push_back({ max(newleft , (*itb)[0]) , (*itb)[1]}) ;
itb++ ;
break ;
}
else
{
if(left > (*itb)[0]) newintes.push_back({(*itb)[0] , left }) ;
left = (*itb)[1] ;
itb++ ;
}
}
newintes.insert(newintes.end() , itb , intes.end() ) ;
intes = newintes ;
}
private :
vector<vector<int> > intes ;
};
/**
* Your RangeModule object will be instantiated and called as such:
* RangeModule* obj = new RangeModule();
* obj->addRange(left,right);
* bool param_2 = obj->queryRange(left,right);
* obj->removeRange(left,right);
*/
解法二:
用orderde map来做,存储[left , right) , m[left] = right ;然后查找m中所有与[left , right)有交集的区间并合并。时间复杂度都为O(logN) ;
class RangeModule {
public:
RangeModule() {
}
void addRange(int left, int right)
{
pair<int , int> inte = find(left , right) ;
m[inte.first] = inte.second ;
}
bool queryRange(int left, int right)
{
auto it = m.upper_bound(left) ;
return it != m.begin() && (--it)->second >= right ;
}
void removeRange(int left, int right)
{
pair<int , int> inte = find(left , right) ;
if(left > inte.first) m[inte.first] = left ;
if(right < inte.second) m[right] = inte.second ;
}
private :
map<int , int > m ;
pair<int , int> find(int left , int right)
{
auto l = m.upper_bound(left) ;
auto r = m.upper_bound(right) ;
if(l != m.begin() && (--l)->second < left) ++l;
if(l == r) return {left , right} ;
left = min(left , l->first) ;
right = max(right , (--r)->second) ;
m.erase(l , ++r) ;
return {left , right} ;
}
};
/**
* Your RangeModule object will be instantiated and called as such:
* RangeModule* obj = new RangeModule();
* obj->addRange(left,right);
* bool param_2 = obj->queryRange(left,right);
* obj->removeRange(left,right);
*/