Skip to content

Commit 5f0449f

Browse files
committed
feat: 218. The Skyline Problem : 扫描线
1 parent 625be56 commit 5f0449f

File tree

2 files changed

+141
-0
lines changed

2 files changed

+141
-0
lines changed
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/**
2+
* @param {number[][]} buildings
3+
* @return {number[][]}
4+
*/
5+
const getSkyline = function (b) {
6+
const a = []; const h = new RemovableHeap((a, b) => b - a)
7+
for (const [l, r, h] of b) {
8+
a.push([l, h, 1])
9+
a.push([r, h, -1])
10+
}
11+
a.sort((x, y) => x[0] - y[0])
12+
const ans = []
13+
for (let i = 0; i < a.length;) {
14+
const x = a[i][0]; let j = i
15+
while (j < a.length && a[j][0] === x) {
16+
const [_, y, f] = a[j]
17+
if (f === -1) h.remove(y)
18+
else h.push(y)
19+
j++
20+
}
21+
i = j
22+
const cur = h.top() ?? 0
23+
if (!ans.length || ans[ans.length - 1][1] !== cur) {
24+
ans.push([x, cur])
25+
}
26+
}
27+
return ans
28+
}
29+
30+
class Heap {
31+
constructor (data = [], compare = (lhs, rhs) => lhs < rhs ? -1 : lhs > rhs ? 1 : 0) {
32+
if (typeof data === 'function') {
33+
compare = data
34+
data = []
35+
}
36+
this.data = [null, ...data]
37+
this.lt = (i, j) => compare(this.data[i], this.data[j]) < 0
38+
for (let i = this.size(); i > 0; i--) { this.heapify(i) }
39+
}
40+
41+
size () {
42+
return this.data.length - 1
43+
}
44+
45+
push (v) {
46+
this.data.push(v)
47+
let i = this.size()
48+
while (i >> 1 !== 0 && this.lt(i, i >> 1)) { this.swap(i, i >>= 1) }
49+
}
50+
51+
pop () {
52+
this.swap(1, this.size())
53+
const top = this.data.pop()
54+
this.heapify(1)
55+
return top
56+
}
57+
58+
top () {
59+
return this.data[1]
60+
}
61+
62+
heapify (i) {
63+
while (true) {
64+
let min = i
65+
const [l, r, n] = [i * 2, i * 2 + 1, this.data.length]
66+
if (l < n && this.lt(l, min)) { min = l }
67+
if (r < n && this.lt(r, min)) { min = r }
68+
if (min !== i) {
69+
this.swap(i, min)
70+
i = min
71+
} else { break }
72+
}
73+
}
74+
75+
clear () {
76+
this.data = [null]
77+
}
78+
79+
swap (i, j) {
80+
const d = this.data;
81+
[d[i], d[j]] = [d[j], d[i]]
82+
}
83+
}
84+
85+
class RemovableHeap {
86+
constructor (data = [], cmp) {
87+
this.heap = new Heap(data, cmp)
88+
this.counts = new Map()
89+
this._invalidCount = 0
90+
for (let i = 1; i < this.heap.data.length; i++) {
91+
this._setCount(this.heap.data[i], 1)
92+
}
93+
}
94+
95+
size () {
96+
return this.heap.size() - this._invalidCount
97+
}
98+
99+
top () {
100+
this._normalize()
101+
return this.heap.top()
102+
}
103+
104+
pop () {
105+
this._normalize()
106+
if (this.heap.size() < 1) { return void 0 }
107+
const top = this.heap.pop()
108+
this._setCount(top, -1)
109+
return top
110+
}
111+
112+
push (num) {
113+
this._setCount(num, 1)
114+
this.heap.push(num)
115+
}
116+
117+
remove (num) {
118+
if (Number(this.counts.get(num)) > 0) {
119+
this._setCount(num, -1)
120+
this._invalidCount++
121+
}
122+
}
123+
124+
has (value) {
125+
return this.counts.get(value) > 0
126+
}
127+
128+
_setCount (num, diff) {
129+
let _a
130+
const count = (_a = this.counts.get(num)) != null ? _a : 0
131+
this.counts.set(num, count + diff)
132+
}
133+
134+
_normalize () {
135+
while (this.heap.size() && !this.counts.get(this.heap.top())) {
136+
this.heap.pop()
137+
this._invalidCount--
138+
}
139+
}
140+
}

leetcode/残酷刷题/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@
273273
### 扫描线 (Sweep Line)
274274

275275
- 56. Merge Intervals
276+
- 218. The Skyline Problem
276277

277278
## Links
278279

0 commit comments

Comments
 (0)