【原创】715. Range Module -- Leetcode 算法笔记

本文介绍了LeetCode 715. Range Module问题的解决方案,通过使用map高效地实现区间添加、删除和查询操作。详细解析了addRange、removeRange和queryRange三个方法的实现逻辑,确保在log(n)时间内完成区间操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

LeetCode 715. Range Module

题目要求高效地实现区间的添加,删除和查询操作。

题目分析:本题是一道设计题,要求实现一个类(Range Module)的三个方法:addRange(int, int), queryRange(int, int) 和 removeRange(int, int)。
该类的对象会穿插地调用这三个方法。听起来有点像并查集,但并查集“一般”不涉及删除操作(不是很确定,只能说“一般”),这道题其实用简单的map就可以实现。
具体来说:map的key是区间的起点,value是区间的终点(其实用set也可以实现,set的元素是个pair<int, int>,自己实现比较函数即可)。
由于map的key是有序的,所以在添加,删除或者查询区间的时候可以用log(n)的时间快速定位到用执行区间操作的位置。

在每次进行区间操作(add, remove or query)之前,区间与区间之间都没有重叠部分,且区间与区间不相邻。

addRange(int left, int right):如果对象里没有任何区间,则直接插入要加的区间即可。否则,利用map<int, int>的lower_bound(int)函数查找第一个左区间大于或者等于left位置iter(时间复杂度是log(n)),接下来分三种情况:

  1. 如果iter == map::end,说明所有左区间都小于left(包括最后一个区间),此时a)如果最后一个区间的右区间小于left,直接插入[left, right)到末尾即可;b)否则,将最后一个区间的右区间只改为右区间和right中较大的一个即可。
  2. 如果iter == map::begin,说明在iter之前没有任何区间,此时从iter开始迭代区间,直到iter == map::end 或者iter的左区间大于left。迭代过程中如果发现当前区间与[left, right)没有交集且不相邻,则跳过此区间,如果相交或者相邻,则将left赋为left和当前左区间中较小的一个,right赋为right和当前右区间较大的一个,并删除当前区间。迭代结束之后将[left, right)加入到map中。
  3. iter在除以上两种情况外的位置,此时iter前的一个区间可能与[left, right)也有交集,所以先将iter–,然后在执行步骤2的操作即可。

removeRange(int left, int right):如果对象里没有任何区间,直接返回。 否则,利用map<int, int>的lower_bound(int)函数查找第一个左区间大于或者等于left位置iter(时间复杂度是log(n)),接下来分三种情况:

  1. 如果iter == map::end,说明所有左区间都小于left(包括最后一个区间),此时a)如果最后一个区间的右区间小于等于left,直接返回即可;b)如果最后一个区间的右区间小于等于right,只需将最后一个右区间的改为left即可;c)如果最后一个区间的右区间小于right,除了将最后一个右区间的改为left,还有插入[right, 最后一个区间的右区间)到对象中。
  2. 如果iter == map::begin,说明在iter之前没有任何区间,此时从iter开始迭代区间,直到iter == map::end 或者 iter的左区间大于等于left。迭代过程中如果发现当前区间与[left, right)没有交集,则跳过此区间,如果相交,可分为以下四种情况:(当前区间的左区间用first表示,当前区间的右区间用second表示)
    a) 如果first <= left && second > right,插入[second, right)当对象中,并删除当前区间;
    b) 如果first <= left && second <= right,删除当前区间即可;
    c) 如果first > left && second <= right,将当前区间的右区间改为left即可;
    d) 如果first > left && second > right,将[right, second)插入对象中,并将当前区间的右区间值改为left。
  3. iter在除以上两种情况外的位置,此时iter前的一个区间可能与[left, right)也有交集,所以先将iter–,然后在执行步骤2的操作即可。

queryRange(int left, int right):如果对象里没有任何区间,返回false。否则,利用map<int, int>的lower_bound(int)函数查找第一个左区间大于或者等于left位置iter(时间复杂度是log(n)),接下来分三种情况:

  1. 如果iter == map::end,说明所有左区间都小于left(包括最后一个区间),此时只需考察最后一个区间的右区间是否大于等于right,是则返回true,否则返回false;
  2. 如果iter == map::begin,情况与1相同,只需考察第一个区间的右区间是否大于等于right,是则返回true,否则返回false;
  3. iter在除以上两种情况外的位置,此时iter前的一个区间可能与[left, right)也有交集,除了考察当前区间是否包含[left, right)以外, 还有考察iter的前一个区间是否包含[left, right)

    class RangeModule {
   
      map<int, int> range;
    public:
      RangeModule() {
   

      }
    
      void addRange(int left, i
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值