Java中的平衡树
给定一堆线段,每个线段都有一个起点、一个终点,用数组[(beg1,end1),(beg2,end2),(beg3,end3)......]来表示。可以提出以下问题:
- 这些线段是否有重合部分
- 这些线段的总长度是多少(多条线段重合部分只计算一次),这个问题相当于上面那个问题的加强版
如果一次性给定了这些线段,只需对这些线段进行排序即可O(nlog(n)),然后从左往右O(n)复杂度扫描一遍。
这道题要求在线算法。所以就需要对每条线段的start进行排序,当插入时,判断start的上界线段、下界线段是否可以容纳当前线段即可。如果用数组实现,每次插入需要O(n/2)的复杂度。如果用平衡树,每次插入需要O(log(n))的复杂度。
这种方法复杂度为O(Nlog(N))
import java.util.TreeMap;
class MyCalendar {
class Node {
int start;
int end;
Node(int start, int end) {
this.start = start;
this.end = end;
}
}
TreeMap<Integer, Node> a = new TreeMap<>();
public MyCalendar() {
a.put(-1, new Node(-1, 0));
a.put((int) (1e9 + 7), new Node((int) (1e9 + 7), (int) (1e9 + 8)));
}
public boolean book(int start, int end) {
Node floor = a.floorEntry(start).getValue();
Node ceil = a.ceilingEntry(start).getValue();
if (start >= floor.end && end <= ceil.start) {
a.put(start, new Node(start, end));
return true;
} else {
return false;
}
}
}
此题还有另一种方法
对于N条线段,每条线段左端点为+1,右端点为-1,从左往右扫描,初始时s=0,遇到左端点s就+1,遇到右端点s就-1,在这个过程中,s的值必然始终为0或者1。
这种方法复杂度为O(N*N),其中N为线段的个数。
这种方法很容易扩展到允许线段交叉2次的情况,只需要改一下从左往右扫描时允许的最大上界即可。题目链接。
class MyCalendar{
public:
map<int, int> delta;
bool book(int start, int end) {
delta[start]++;
delta[end]--;
int booked = 0;
for (auto &d : delta) {
booked += d.second;
if (booked ==2) {
delta[start]--;
delta[end]++;
return false;
}
}
return true;
}
};
最后补充一个小技巧:一维数轴上,如何判断两条线段相交?
问题可以转化为:一位数轴上,如何求两条线段公共部分的长度?
记线段1(a0,a1),线段2(b0,b1)
答案是:min(a1,b1)-max(a0,b0)
于是两条线段相交的充要条件是:min(a1,b1)>max(a0,b0)
Java中的平衡树的更多相关文章
- java中的锁
java中有哪些锁 这个问题在我看了一遍<java并发编程>后尽然无法回答,说明自己对于锁的概念了解的不够.于是再次翻看了一下书里的内容,突然有点打开脑门的感觉.看来确实是要学习的最好方式 ...
- java中的字符串相关知识整理
字符串为什么这么重要 写了多年java的开发应该对String不陌生,但是我却越发觉得它陌生.每学一门编程语言就会与字符串这个关键词打不少交道.看来它真的很重要. 字符串就是一系列的字符组合的串,如果 ...
- Java中的Socket的用法
Java中的Socket的用法 Java中的Socket分为普通的Socket和NioSocket. 普通Socket的用法 Java中的 ...
- java中Action层、Service层和Dao层的功能区分
Action/Service/DAO简介: Action是管理业务(Service)调度和管理跳转的. Service是管理具体的功能的. Action只负责管理,而Service负责实施. DAO只 ...
- Java中常用集合操作
一.Map 名值对存储的. 常用派生类HashMap类 添加: put(key,value)往集合里添加数据 删除: clear()删除所有 remove(key)清除单个,根据k来找 获取: siz ...
- java中的移位运算符:<<,>>,>>>总结
java中有三种移位运算符 << : 左移运算符,num << 1,相当于num乘以2 >> : 右移运算符,num >& ...
- 关于Java中进程和线程的详解
一.进程:是程序的一次动态执行,它对应着从代码加载,执行至执行完毕的一个完整的过程,是一个动态的实体,它有自己的生命 周期.它因创建而产生,因调度而运行,因等待资源或事件而被处于等待状态,因完成任务而 ...
- Java中的进程和线程
Java中的进程与线程 一:进程与线程 概述:几乎任何的操作系统都支持运行多个任务,通常一个任务就是一个程序,而一个程序就是一个进程.当一个进程运行时,内部可能包括多个顺序执行流,每个顺序执行流就是 ...
- Java中的进程与线程(总结篇)
详细文档: Java中的进程与线程.rar 474KB 1/7/2017 6:21:15 PM 概述: 几乎任何的操作系统都支持运行多个任务,通常一个任务就是一个程序,而一个程序就是一个进程.当一个进 ...
随机推荐
- 《MacTalk·人生元编程》
<MacTalk·人生元编程> 基本信息 <MacTalk·人生元编程> 基本信息 作者:池建强 出版社:人民邮电出版社 ISBN:9787115342232 上架时间:201 ...
- Javascript时间以及格式化秒
var now = new Date(); timer = $.timer(timeout, function () { var sec_num = Math.ceil((now.getTim ...
- #line 的作用是改变当前行数和文件名称
#line 的作用是改变当前行数和文件名称,它们是在编译程序中预先定义的标识符命令的基本形式如下: #line number["filename"]其中[]内的文件名可以省略. ...
- C语言union关键字,union和struct区别
union 关键字的用法与struct 的用法非常类似. union 维护足够的空间来置放多个数据成员中的“一种”,而不是为每一个数据成员配置空间,在union 中所有的数据成员共用一个空间,同一时间 ...
- 显示Mysql中的所有用户
在mysql中如何显示所有用户? 1.show databases显示所有数据库 2.show tables显示所有数据表 3.select current_user();显示当前用户 4.显示所有用 ...
- Objective-C:NSArray的常见操作
NSArray不可变字符串的主要操作有:创建.枚举.排序.与NSString之间的相互转换 注意: NSArray可以存对象,不可以存基本数据类型.结构体.数组.指针.nil.NULL NSArray ...
- 第十四章 springboot + profile(不同环境读取不同配置)
具体做法: 不同环境的配置设置一个配置文件,例如:dev环境下的配置配置在application-dev.properties中:prod环境下的配置配置在application-prod.prope ...
- 为什么谷歌的JSON响应以while(1);开头?
问题(QUESTION): 我有个问题一直很好奇就是:为什么谷歌的JSON响应以while(1);开头?举个例子,当把谷歌日历打开和关掉时,会返回这样的JSON对象: while(1);[['u',[ ...
- Linq-语句之存储过程
存储过程 在我们编写程序中,往往需要一些存储过程,在LINQ to SQL中怎么使用呢?也许比原来的更简单些.下面我们以NORTHWND.MDF数据库中自带的几个存储过程来理解一下. 1.标量返回 在 ...
- Mongo命令批量更新某一数组字段的顺序
db.table.find().forEach(function (doc) { var oldValue = doc.Column1; var newValue = [sa[1] ...