题目:
实现一个 MyCalendar
类来存放你的日程安排。如果要添加的日程安排不会造成 重复预订 ,则可以存储这个新的日程安排。
当两个日程安排有一些时间上的交叉时(例如两个日程安排都在同一时间内),就会产生 重复预订 。
日程可以用一对整数 start
和 end
表示,这里的时间是半开区间,即 [start, end)
, 实数 x
的范围为, start <= x < end
。
实现 MyCalendar
类:
MyCalendar()
初始化日历对象。boolean book(int start, int end)
如果可以将日程安排成功添加到日历中而不会导致重复预订,返回true
。否则,返回false
并且不要将该日程安排添加到日历中。
算法:
[start1, [start2, end1), end2] 如果start1 < end2 && start2 < end1则说明区间相交。
方法一:模拟
type MyCalendar struct {
Calendar [][]int
}
func Constructor() MyCalendar {
return MyCalendar{make([][]int, 0)}
}
func (this *MyCalendar) Book(start int, end int) bool {
for _, p := range this.Calendar {
if p[0] < end && start < p[1] {
return false
}
}
this.Calendar = append(this.Calendar, []int{start, end})
return true
}
方法二: 线段树
type MyCalendar struct {
tree, lazy map[int]bool
}
func Constructor() MyCalendar {
return MyCalendar{
tree: make(map[int]bool),
lazy: make(map[int]bool),
}
}
func (this *MyCalendar) Book(start int, end int) bool {
if this.query(start, end - 1, 0, 1e9, 1) {
return false
}
this.update(start, end - 1, 0, 1e9, 1)
return true
}
func (this *MyCalendar) query(start, end, left, right, idx int) bool {
if end < left || right < start {
return false
}
if this.lazy[idx] {
return true
}
if start <= left && right <= end {
return this.tree[idx]
}
mid := (left + right) >> 1
return this.query(start, end, left, mid, 2 * idx) || this.query(start, end, mid + 1, right, 2 * idx + 1)
}
func (this *MyCalendar) update(start, end, left, right, idx int) {
if end < left || right < start {
return
}
if start <= left && right <= end {
this.tree[idx] = true
this.lazy[idx] = true
} else {
mid := (left + right) >> 1
this.update(start, end, left, mid, 2 * idx)
this.update(start, end, mid + 1, right, 2 * idx + 1)
this.tree[idx] = true
if this.lazy[2 * idx] && this.lazy[2 * idx + 1] {
this.lazy[idx] = true
}
}
}
/**
* Your MyCalendar object will be instantiated and called as such:
* obj := Constructor();
* param_1 := obj.Book(start,end);
*/
线段树二:
这个模板不错,偷了
type MyCalendar struct {
Left, Right int
Val, Lazy int
LeftChild, RightChild *MyCalendar
}
func Constructor() MyCalendar {
return MyCalendar{
Left:0,
Right:1e9,
}
}
func NewNode(left, right int) *MyCalendar {
return &MyCalendar{
Left: left,
Right: right,
}
}
func (this *MyCalendar) Book(start int, end int) bool {
if this.query(start, end -1) > 0 {
return false
}
this.update(start, end - 1, 1)
return true
}
func (this *MyCalendar) query(start, end int) int {
// 如果node在区间内
// 当前节点表示的整个区间在查询目标区间内,返回,和其他的区间加起来
if start <= this.Left && this.Right <= end {
return this.Val
}
// 为什么要lazycreate呢,因为this的范围可能是[2,9],而query的参数可能是[3,3],所以需要吧this的子节点动态生成出来
this.lazyCreate()
// push down
this.pushdown()
mid := this.Left + (this.Right - this.Left) / 2
if end <= mid {
return this.LeftChild.query(start, end)
// 为什么mid == start 不能走这个逻辑?
// 因为小于等于mid是this的左节点管,大于mid的值是this的右节点管啊
} else if mid < start {
return this.RightChild.query(start, end)
}
// 拆分start, end区间求结果
return this.LeftChild.query(start, mid) + this.RightChild.query(mid + 1, end)
}
func (this *MyCalendar) lazyCreate() {
mid := this.Left + (this.Right - this.Left) / 2
if this.LeftChild == nil {
this.LeftChild = NewNode(this.Left, mid)
}
if this.RightChild == nil {
this.RightChild = NewNode(mid + 1, this.Right)
}
}
func (this *MyCalendar) pushdown() {
if this.Lazy == 0 {
return
}
this.LeftChild.Val = this.LeftChild.Val + (this.LeftChild.Right - this.LeftChild.Left + 1) * this.Lazy
this.RightChild.Val = this.RightChild.Val + (this.RightChild.Right - this.RightChild.Left + 1) * this.Lazy
this.LeftChild.Lazy = this.Lazy
this.RightChild.Lazy = this.Lazy
this.Lazy = 0
}
func (this *MyCalendar) update(start, end, val int) {
if end < this.Left || this.Right < start {
return
}
if start <= this.Left && this.Right <= end {
this.Lazy = val
this.Val = (this.Right - this.Left + 1) * val
} else {
this.lazyCreate()
this.pushdown()
this.LeftChild.update(start, end, val)
this.RightChild.update(start, end, val)
this.Val = this.LeftChild.Val + this.RightChild.Val
}
}
/**
* Your MyCalendar object will be instantiated and called as such:
* obj := Constructor();
* param_1 := obj.Book(start,end);
*/