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 概述: 几乎任何的操作系统都支持运行多个任务,通常一个任务就是一个程序,而一个程序就是一个进程.当一个进 ...
随机推荐
- 通过Web启动本地应用程序
通过自定义协议在Web中启动本地应用程序 实例是打开本地安装的Word程序 注册自己的协议Windows Registry Editor Version 5.00 [HKEY_CLASSES_RO ...
- 最近在研究FFmpeg编解码
好几年没上CNBLOGS了, 最近在研究FFmpeg编解码,一个人研究感到很寂寞,所以想通过博客来和大家分享和交流,呵呵. 最近研究的主题是: ANDROID手机同屏技术: 需要用到ANDROID截屏 ...
- founder面试题
.写出正面程序支行结果: #include<iostream> using namespace std; void func(int a) { static int c = a; c++; ...
- Furure的简单介绍和使用
引子:
- OpenCV学习(38) 人脸识别(3)
前面我们学习了基于特征脸的人脸识别,现在我们学习一下基于Fisher脸的人脸识别,Fisher人脸识别基于LDA(线性判别算法)算法,算法的详细介绍可以参考下面两篇教程内容: ...
- 【Todo】React & Nodejs学习 &事件驱动,非阻塞IO & JS知识栈:Node为主,JQuery为辅,Bootstrap & React为辅辅,其他如Angular了解用途即可
JS知识栈:Node为主,JQuery为辅,Bootstrap & React为辅辅,其他如Angular了解用途即可 今天在学习ReactJS和NodeJS,看到关于ReactJS的这篇文章 ...
- SonarQube代码质量管理平台 的安装、配置与使用
SonarQube是管理代码质量一个开放平台,可以快速的定位代码中潜在的或者明显的错误,下面将会介绍一下这个工具的安装.配置以及使用. 准备工作: 1.jdk(不再介绍) 2.sonarqube:ht ...
- 利用WebClient实现对Http协议的Post和Get对网站进行模拟登陆和浏览
我们在一些场合经常需要模拟浏览器进行一些操作,比如模拟投票,或者模拟点击,或者Web游戏外挂.而C#中封装好的WebClient可以在某些要求不算搞的场景实现Http的Post和Get.具体请见代码: ...
- SQL基础(五):SQL函数
一.SQL Aggregate 函数: SQL Aggregate 函数计算从列中取得的值,返回一个单一的值. 1.AVG() 函数 AVG() 函数返回数值列的平均值. 语法:SELECT AVG( ...
- Java基础(三):修饰符、运算符、循环结构和分支结构
一.Java修饰符: Java语言提供了很多修饰符,主要分为以下两类:访问修饰符和非访问修饰符.修饰符用来定义类.方法或者变量,通常放在语句的最前端. 1.访问控制修饰符: Java中,可以使用访问控 ...