- 为了快速得到一段连续区间的左右端点:利用左端点,快速求得右端点;利用右端点,快速求得左端点。我们可以建立两个左右端点映射
L,R
。L[p
]映射这段连续区间的左端点,R[p]
映射这段连续区间的右端点:给区间[l,r]
,L[r]=l, R[l]=r
。
1. LeetCode 352
- 分析题意,直接可以分两种情况。
- 1、val在某段区间里,那么直接return;
- 2、不在某段区间里,这个时候我们就要看左右两边是否有和它相交的区间。假如左边有个区间和它相交,我们需要快速得到这个区间的左端点,利用
l[val-1]
,并且需要修改这个左端点对应新连续区间的新右端点:r[l[val-1]]=val
。然后还要将这个新区间右边的端点val
的左链映射到左端点l[val-1]
。最后在左端点的区间映射里,删除原来右端点的左链l[val-1]
。
class SummaryRanges {
private:
map<int, int> l, r;
public:
/** Initialize your data structure here. */
SummaryRanges() {
l.clear(); r.clear();
}
void addNum(int val) {
// 先判断是否已经在某个区间里
if (r.size()){
auto it = r.upper_bound(val);
if (it != r.begin()){
--it;
if (it->second >= val) return;
}
}
int left = l.count(val - 1), right = r.count(val + 1);
if (left && right){
r[l[val - 1]] = r[val + 1];
l[r[val + 1]] = l[val - 1];
l.erase(val - 1);
r.erase(val + 1);
}
else if (left){
l[val] = l[val - 1];
r[l[val - 1]] = val;
l.erase(val - 1);
}
else if (right){
r[val] = r[val + 1];
l[r[val + 1]] = val;
r.erase(val + 1);
}
else {
l[val] = r[val] = val;
}
}
vector<vector<int>> getIntervals() {
vector<vector<int>> ans;
for (const auto &el: r) ans.push_back({el.first, el.second});
return ans;
}
};
/**
* Your SummaryRanges object will be instantiated and called as such:
* SummaryRanges* obj = new SummaryRanges();
* obj->addNum(val);
* vector<vector<int>> param_2 = obj->getIntervals();
*/
2. LeetCode 5497
传送门:https://leetcode-cn.com/problems/find-latest-group-of-size-m/
class Solution {
private:
static constexpr int N = 1e5 + 5;
int l[N], r[N];
int get(int p){ // 以p为左端点的连续1长度
return r[p] - p + 1;
}
public:
int findLatestStep(vector<int>& arr, int m) {
memset(l, 0, sizeof(l));
memset(r, 0, sizeof(r));
int n = arr.size(), res = -1, cnt = 0;
// 只需要不断更新每个端点的左右链就好了 反正求长度的时候 只管端点的位置
for (int i = 0; i < n; ++i){
int p = arr[i];
if (!l[p - 1] && !r[p + 1]){
l[p] = r[p] = p; // 先指向自己
if (m == 1) cnt++;
}
else if (l[p - 1] && r[p + 1]){
if (get(l[p - 1]) == m) --cnt;
if (get(p + 1) == m) --cnt;
r[l[p - 1]] = r[p + 1];
l[r[p + 1]] = l[p - 1];
if (get(l[p - 1]) == m) ++cnt;
}
else if (l[p - 1]){
if (get(l[p - 1]) == m) --cnt;
l[p] = l[p - 1]; // 更新这段最右边端点的左链
r[l[p - 1]] = p; // 更新最左边端点的右链
if (get(l[p]) == m) ++cnt;
}
else if (r[p + 1]){
if (get(p + 1) == m) --cnt;
r[p] = r[p + 1];
l[r[p + 1]] = p;
if (get(p) == m) ++cnt;
}
if (cnt > 0) res = i + 1;
}
return res;
}
};