leetcode:715. Range 模块

题目来源

题目描述

在这里插入图片描述

在这里插入图片描述

class RangeModule {
private:
public:
    RangeModule() {
    }

    void addRange(int start, int end) {
    
    }

    bool queryRange(int start, int end) {

    }

    void removeRange(int start, int end) {

    }
};


题目分析

题意

  • 这道题让我们实现一个RangeModule的类,里面有三个功能函数:
    • 插入范围
    • 查找范围
    • 删除范围

区间操作

(1) 插入操作就是57. insert interval这道题

(2) 查找范围:

  • 查找是否有一个范围完全覆盖了要查找的范围;如果有,返回true;否则返回false

(3) 删除范围

  • 类似插入范围。
  • 已知待删除的范围是deleteInterval = [start,end),现有范围是Intervals
  • 我们先新建一个res存结果
  • 然后遍历已有的范围Intervals:
    • 如果currInterval.end <= deleteInterval.start,说明没有重叠,将currInterval压入res,并且curr++来记录当前位置
    • 如果deleteInterval.end <= currInterval.start,说明没有重叠,将currInterval压入res
    • 否则就是有重叠。需要删除:删除时可能将原来的大范围变为两个/一个/零个小范围,所以我们用一个临时数组t来存break掉后的小范围。
      • 如果当前范围的起始位置小于要删除的范围的起始位置left,说明此时一定有一段范围留下来了,即从当前范围的起始位置到要删除的范围的起始位置left,将这段范围加入临时数组t
      • 同理,如果当前范围的结束位置大于要删除的范围的结束位置right,将这段范围加入临时数组t。
    • 最后将数组t加入结果res中的cur位置即可
class RangeModule {
private:
    std::vector<std::pair<int, int>> intervals;
public:
    RangeModule() {
    }

    void addRange(int start, int end) {
        std::vector<std::pair<int, int>> res;
        int n = intervals.size(), curr = 0;
        for (int i = 0; i < n; ++i) {
            if(intervals[i].second < start){
                res.push_back(intervals[i]);
                ++curr;
            }else if(end < intervals[i].first ){
                res.push_back(intervals[i]);
            }else{
                start = std::min(start, intervals[i].first);
                end = std::max(end, intervals[i].second);
            }
        }
        res.insert(res.begin() + curr, {start, end});
        intervals = res;
    }

    bool queryRange(int start, int end) {
        for(auto  a : intervals){
            if(a.first <= start && a.second >= end){
                return true;
            }
        }
        return false;
    }

    void removeRange(int start, int end) {
        vector<pair<int, int>> res, t;
        int n = intervals.size(), cur = 0;
        for (int i = 0; i < n; ++i) {
            if (intervals[i].second <= start) {
                res.push_back(intervals[i]);
                ++cur;
            } else if (intervals[i].first >= end) {
                res.push_back(intervals[i]);
            } else {
                if (intervals[i].first < start) {
                    t.push_back({intervals[i].first, start});
                }
                if (intervals[i].second > end) {
                    t.push_back({end, intervals[i].second});
                }
            }
        }
        res.insert(res.begin() + cur, t.begin(), t.end());
        intervals = res;
    }
};

动态开点线段树

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值