LeetCode解析------715.Range模块

题目:

Range 模块是跟踪数字范围的模块。你的任务是以一种有效的方式设计和实现以下接口。
addRange(int left, int right) 添加半开区间 [left, right),跟踪该区间中的每个实数。添加与当前跟踪的数字部分重叠的区间时,应当添加在区间[left, right) 中尚未跟踪的任何数字到该区间中。
queryRange(int left, int right) 只有在当前正在跟踪区间 [left, right) 中的每一个实数时,才返回 true。
removeRange(int left, int right) 停止跟踪区间 [left, right) 中当前正在跟踪的每个实数。

示例:
addRange(10, 20): null
removeRange(14, 16): null
queryRange(10, 14): true (区间 [10, 14) 中的每个数都正在被跟踪)
queryRange(13, 15): false (未跟踪区间 [13, 15) 中像 14, 14.03, 14.17 这样的数字)
queryRange(16, 17): true (尽管执行了删除操作,区间 [16, 17) 中的数字 16 仍然会被跟踪)

提示:

半开区间 [left, right) 表示所有满足 left <= x < right 的实数。
对 addRange, queryRange, removeRange 的所有调用中 0 < left < right < 10^9。
在单个测试用例中,对addRange 的调用总数不超过 1000 次。
在单个测试用例中,对 queryRange 的调用总数不超过 5000 次。
在单个测试用例中,对 removeRange 的调用总数不超过 1000 次。*

简单介绍:
题目:Range模块
题目难度:困难
使用语言:JAVA。
这道题来自leetcode题库的Ordered Map标签。
如果想要加深对java拥有数据结构类型的理解,特别是Map的理解,做这类型的题是提升很快的。

解题思路:
首先看题、分析题意,我们可以明确几个关键点,分别是跟踪区间的添加、查询、删除。
既然,我们已经分析出来题目的关键任务了,下面我们就可以开始思考实现了。
我们采用算法与数据结构的思路来剖析一下这题,

数据结构:
要实现对数据的操作,我们要先明确存储数据的数据结构。该题的数据结构的作用,是保存跟踪区间。根据跟踪区间的特性,我们可以采用有序的数据集合-TreeSet来保存跟踪区间。同时,使用一个Interval类来存储一段追踪区间。

算法:
既然明确了TreeSet和Interval作为解决该题的数据集合,我们就可以开始我们的算法分析了。
1.添加追踪区间,取新区间和已有追踪区间的并集。
2.查询现有追踪区间是否可以完全覆盖给定区间,若有则返回true,否则返回false。
3.移除追踪区间,返回0个、1个、2个被截断的追踪区间,加入ranges。

复杂度分析:

时间复杂度:
设 K 为 ranges 中的元素个数,那么 addRange() 和 removeRange() 的时间复杂度为O(K),queryRange() 的时间复杂度为 O(log K)。
更具体地,如果有 A次addRange() 操作,R 次 removeRange() 操作和 Q 次 queryRange() 操作,那么总的时间复杂度为O((A+R)^2+Qlog(A+R))。

空间复杂度
O(A+R)。

代码部分:

import java.util.*;

public class RangeModule {
	TreeSet<Interval> ranges;
	public RangeModule() {
		ranges=new TreeSet<>();
	}
	//添加追踪区间,取新区间和以有追踪区间的并集
	public void addRange(int left,int right) {
		Iterator<Interval> itr=ranges.tailSet(new Interval(0,left-1)).iterator();
		while(itr.hasNext()) {
			Interval iv=itr.next();
			if(iv.left>right) break;
			left=Math.min(left, iv.left);
			right=Math.max(right, iv.right);
			itr.remove();
		}
		ranges.add(new Interval(left,right));
	}
	//查询现有追踪区间是否可以完全覆盖给定区间
	public boolean queryRange(int left,int right) {
		Interval iv=ranges.higher(new Interval(0,left));
		return (iv!=null&&iv.left<=left&&iv.right>=right);
	}
	//移除追踪区间,返回0个、1个、2个被截断的追踪区间,加入ranges
	public void removeRange(int left,int right) {
		Iterator<Interval> itr=ranges.tailSet(new Interval(0,left)).iterator();
		ArrayList<Interval> todo=new ArrayList<>();
		while(itr.hasNext()) {
			Interval iv=itr.next();
			if(iv.left>right)break;
			if(iv.left<left) todo.add(new Interval(iv.left,left));
			if(iv.right>right) todo.add(new Interval(right,iv.right));
			itr.remove();
		}
		for(Interval iv:todo) ranges.add(iv);
		
	}
}


class Interval implements Comparable<Interval>{
	int left;
	int right;
	public Interval(int left,int right){
		this.left=left;
		this.right=right;
	}
	public int compareTo(Interval that) {
		if(this.right==that.right) {
			return this.left-that.left;
		}
		return this.right-that.right;
	}
}

结语:
晚安!晚安!晚安!晚安!晚安!晚安!晚安!晚安!晚安!晚安!

发布了5 篇原创文章 · 获赞 3 · 访问量 108

猜你喜欢

转载自blog.csdn.net/weixin_44337475/article/details/105577806