【教3妹学编程-算法题】Range 模块

3妹 :哈哈哈哈哈哈哈哈
2哥 : 3妹看什么呢,笑的这么开森
3妹 :2哥你快来看啊,成都欢乐谷的NPC模仿"唐僧", 太搞笑了。
2哥 : 哦这个我也看到了,真的是唯妙唯肖,不能说像,只能说一模一样。
3妹 :哈哈哈哈,西游记翻拍都可以找他助演了~
2哥 :3妹今天刷题了嘛?说到模仿,我们今天来做一个模块的题吧~
3妹:咦,2哥你这个弯,拐的有点急啊。 不过是到了刷题时间了, 让我来看一下吧~

题目:

Range模块是跟踪数字范围的模块。设计一个数据结构来跟踪表示为 半开区间 的范围并查询它们。

半开区间 [left, right) 表示所有 left <= x < right 的实数 x 。

实现 RangeModule 类:

RangeModule() 初始化数据结构的对象。

void addRange(int left, int right) 添加 半开区间 [left, right),跟踪该区间中的每个实数。添加与当前跟踪的数字部分重叠的区间时,应当添加在区间 [left, right) 中尚未跟踪的任何数字到该区间中。

boolean queryRange(int left, int right) 只有在当前正在跟踪区间 [left, right) 中的每一个实数时,才返回 true ,否则返回 false 。

void removeRange(int left, int right) 停止跟踪 半开区间 [left, right) 中当前正在跟踪的每个实数。

示例 1:

输入

"RangeModule", "addRange", "removeRange", "queryRange", "queryRange", "queryRange"

\[\], \[10, 20\], \[14, 16\], \[10, 14\], \[13, 15\], \[16, 17\]

输出

null, null, null, true, false, true

解释

RangeModule rangeModule = new RangeModule();

rangeModule.addRange(10, 20);

rangeModule.removeRange(14, 16);

rangeModule.queryRange(10, 14); 返回 true (区间 [10, 14) 中的每个数都正在被跟踪)

rangeModule.queryRange(13, 15); 返回 false(未跟踪区间 [13, 15) 中像 14, 14.03, 14.17 这样的数字)

rangeModule.queryRange(16, 17); 返回 true (尽管执行了删除操作,区间 [16, 17) 中的数字 16 仍然会被跟踪)

提示:

1 <= left < right <= 10^9

在单个测试用例中,对 addRange 、 queryRange 和 removeRange 的调用总数不超过 10^4 次

思路:

列表+二分查找

详见代码:

java代码:

复制代码
class RangeModule {
    TreeMap<Integer, Integer> intervals;

    public RangeModule() {
        intervals = new TreeMap<Integer, Integer>();
    }

    public void addRange(int left, int right) {
        Map.Entry<Integer, Integer> entry = intervals.higherEntry(left);
        if (entry != intervals.firstEntry()) {
            Map.Entry<Integer, Integer> start = entry != null ? intervals.lowerEntry(entry.getKey()) : intervals.lastEntry();
            if (start != null && start.getValue() >= right) {
                return;
            }
            if (start != null && start.getValue() >= left) {
                left = start.getKey();
                intervals.remove(start.getKey());
            }
        }
        while (entry != null && entry.getKey() <= right) {
            right = Math.max(right, entry.getValue());
            intervals.remove(entry.getKey());
            entry = intervals.higherEntry(entry.getKey());
        }
        intervals.put(left, right);
    }

    public boolean queryRange(int left, int right) {
        Map.Entry<Integer, Integer> entry = intervals.higherEntry(left);
        if (entry == intervals.firstEntry()) {
            return false;
        }
        entry = entry != null ? intervals.lowerEntry(entry.getKey()) : intervals.lastEntry();
        return entry != null && right <= entry.getValue();
    }

    public void removeRange(int left, int right) {
        Map.Entry<Integer, Integer> entry = intervals.higherEntry(left);
        if (entry != intervals.firstEntry()) {
            Map.Entry<Integer, Integer> start = entry != null ? intervals.lowerEntry(entry.getKey()) : intervals.lastEntry();
            if (start != null && start.getValue() >= right) {
                int ri = start.getValue();
                if (start.getKey() == left) {
                    intervals.remove(start.getKey());
                } else {
                    intervals.put(start.getKey(), left);
                }
                if (right != ri) {
                    intervals.put(right, ri);
                }
                return;
            } else if (start != null && start.getValue() > left) {
                if (start.getKey() == left) {
                    intervals.remove(start.getKey());
                } else {
                    intervals.put(start.getKey(), left);
                }
            }
        }
        while (entry != null && entry.getKey() < right) {
            if (entry.getValue() <= right) {
                intervals.remove(entry.getKey());
                entry = intervals.higherEntry(entry.getKey());
            } else {
                intervals.put(right, entry.getValue());
                intervals.remove(entry.getKey());
                break;
            }
        }
    }
}
相关推荐
小超人诞生日记1 小时前
C++ 智能指针的使用及其原理详解
c++·算法
AiNightVision4 小时前
无人机夜视模块如何选择?——从参数指标到系统集成的完整选型指南
人工智能·算法·计算机视觉·车载系统·无人机·视频·智能硬件
牧羊人.3335 小时前
卷积神经网络之VGG
人工智能·深度学习·神经网络·算法·cnn
小郎君6586 小时前
Vue 多标签页的加载态设计:为什么我没有用 Suspense 实现 PageLoading
vue.js·算法
JJJennie7776 小时前
MAI Gateway私有化部署全攻略:大模型网关如何接入?附架构图
算法·gateway·ai网关·魔芋ai
東隅已逝,桑榆非晚7 小时前
算法3.双指针法-快乐数
c++·笔记·学习·算法
专注仿真7 小时前
卷积神经网络(CNN)算法详解
人工智能·python·算法·代码·大模型训练
FII工业富联科技服务7 小时前
多智能体如何进入制造现场?从业务协同到数字孪生验证
大数据·人工智能·算法·机器人·制造·数字孪生
≮傷£≯√7 小时前
httpserver_QNetWorkClient
算法