解法一:二分法。维护一个有序数组,这样在查找和删除的时候时间复杂度都为,空间复杂度。
class SeatManager {
arr: number[]
constructor(n: number) {
this.arr = [0]
}
reserve(): number {
// 找到第一个arr[idx]!=idx的并插入
if (this.arr.length == 1) {
this.arr.push(1)
return 1
} else {
let l = 1, r = this.arr.length-1
while (l!=r) {
let m = (l+r)>>1
if (this.arr[m]==m) l = m+1
else r = m
}
if (l<this.arr.length&&l==this.arr[l]) {
this.arr.push(l+1)
return l+1
}
this.arr.splice(l, 0, l)
return l
}
}
unreserve(seatNumber: number): void {
if (this.arr.length == 0) return
let l = 0, r = this.arr.length-1
while (l!=r) {
let m = (l+r)>>1
if (this.arr[m]==seatNumber) {
this.arr.splice(m, 1)
return
} else if (this.arr[m]>seatNumber) r = m
else l = m+1
}
if (l>=0&&l<this.arr.length&&this.arr[l]==seatNumber) {
this.arr.splice(l,1)
}
}
}
解法二:维护一个小根堆。js没有提供相应的库,只能手写。维护一棵可用数堆,堆本质是一棵完全二叉树,因此我们使用数组保存。父子结点的关系为left_idx=parent_idx*2+1,right_idx=parent_idx*2+2
。每次reserve时选择堆的根节点,然后将最后一个数放到前面重新向下调整;unreserve时把该数加入数组最后,然后向上调整,向上调整到上不去了再向下调整。最后构造函数时间复杂度;reserve函数时间复杂度;unreserve函数时间复杂度。以上算法的前提是输入都是有效的。
class SeatManager {
heap: number[]
constructor(n: number) {
this.heap = []
for (let i = 1; i <= n; i++) this.heap.push(i)
}
reserve(): number {
if (this.heap.length==1) return this.heap.pop()
const res = this.heap[0]
this.heap[0] = this.heap.pop()
let idx = 0
// 往下调整
const inf = Number.MAX_SAFE_INTEGER
while (idx<this.heap.length) {
let idx_l = idx*2+1, idx_r = idx*2+2
let left = inf, right = inf
if (idx_l<this.heap.length) left = this.heap[idx_l]
if (idx_r<this.heap.length) right = this.heap[idx_r]
if (left<right&&left<this.heap[idx]) {
[this.heap[idx],this.heap[idx_l]] = [this.heap[idx_l],this.heap[idx]]
idx = idx_l
}
else if (right<left&&right<this.heap[idx]) {
[this.heap[idx],this.heap[idx_r]] = [this.heap[idx_r],this.heap[idx]]
idx = idx_r
} else break
}
return res
}
unreserve(seatNumber: number): void {
this.heap.push(seatNumber)
// 向上调整
let idx = this.heap.length-1
while (idx>0) {
if (this.heap[Math.floor((idx-1)/2)]>this.heap[idx]) {
[this.heap[Math.floor((idx-1)/2)],this.heap[idx]] = [this.heap[idx],this.heap[Math.floor((idx-1)/2)]]
idx = Math.floor((idx-1)/2)
} else break
}
// 向下调整
const inf = Number.MAX_SAFE_INTEGER
while (idx<this.heap.length) {
let idx_l = idx*2+1, idx_r = idx*2+2
let left = inf, right = inf
if (idx_l<this.heap.length) left = this.heap[idx_l]
if (idx_r<this.heap.length) right = this.heap[idx_r]
if (left<right&&left<this.heap[idx]) {
[this.heap[idx],this.heap[idx_l]] = [this.heap[idx_l],this.heap[idx]]
idx = idx_l
}
else if (right<left&&right<this.heap[idx]) {
[this.heap[idx],this.heap[idx_r]] = [this.heap[idx_r],this.heap[idx]]
idx = idx_r
} else break
}
}
}