mirror of
https://github.com/halfrost/LeetCode-Go.git
synced 2025-07-05 00:25:22 +08:00
217 lines
3.9 KiB
Go
217 lines
3.9 KiB
Go
package leetcode
|
||
|
||
import (
|
||
"sort"
|
||
|
||
"github.com/halfrost/LeetCode-Go/template"
|
||
)
|
||
|
||
// 解法一 线段树 Segment Tree,时间复杂度 O(n log n)
|
||
func getSkyline(buildings [][]int) [][]int {
|
||
st, ans, lastHeight, check := template.SegmentTree{}, [][]int{}, 0, false
|
||
posMap, pos := discretization218(buildings)
|
||
tmp := make([]int, len(posMap))
|
||
st.Init(tmp, func(i, j int) int {
|
||
return max(i, j)
|
||
})
|
||
for _, b := range buildings {
|
||
st.UpdateLazy(posMap[b[0]], posMap[b[1]-1], b[2])
|
||
}
|
||
for i := 0; i < len(pos); i++ {
|
||
h := st.QueryLazy(posMap[pos[i]], posMap[pos[i]])
|
||
if check == false && h != 0 {
|
||
ans = append(ans, []int{pos[i], h})
|
||
check = true
|
||
} else if i > 0 && h != lastHeight {
|
||
ans = append(ans, []int{pos[i], h})
|
||
}
|
||
lastHeight = h
|
||
}
|
||
return ans
|
||
}
|
||
|
||
func discretization218(positions [][]int) (map[int]int, []int) {
|
||
tmpMap, posArray, posMap := map[int]int{}, []int{}, map[int]int{}
|
||
for _, pos := range positions {
|
||
tmpMap[pos[0]]++
|
||
tmpMap[pos[1]-1]++
|
||
tmpMap[pos[1]]++
|
||
}
|
||
for k := range tmpMap {
|
||
posArray = append(posArray, k)
|
||
}
|
||
sort.Ints(posArray)
|
||
for i, pos := range posArray {
|
||
posMap[pos] = i
|
||
}
|
||
return posMap, posArray
|
||
}
|
||
|
||
func max(a int, b int) int {
|
||
if a > b {
|
||
return a
|
||
}
|
||
return b
|
||
}
|
||
|
||
// 解法二 扫描线 Sweep Line,时间复杂度 O(n log n)
|
||
func getSkyline1(buildings [][]int) [][]int {
|
||
size := len(buildings)
|
||
es := make([]E, 0)
|
||
for i, b := range buildings {
|
||
l := b[0]
|
||
r := b[1]
|
||
h := b[2]
|
||
// 1-- enter
|
||
el := NewE(i, l, h, 0)
|
||
es = append(es, el)
|
||
// 0 -- leave
|
||
er := NewE(i, r, h, 1)
|
||
es = append(es, er)
|
||
}
|
||
skyline := make([][]int, 0)
|
||
sort.Slice(es, func(i, j int) bool {
|
||
if es[i].X == es[j].X {
|
||
if es[i].T == es[j].T {
|
||
if es[i].T == 0 {
|
||
return es[i].H > es[j].H
|
||
}
|
||
return es[i].H < es[j].H
|
||
}
|
||
return es[i].T < es[j].T
|
||
}
|
||
return es[i].X < es[j].X
|
||
})
|
||
pq := NewIndexMaxPQ(size)
|
||
for _, e := range es {
|
||
curH := pq.Front()
|
||
if e.T == 0 {
|
||
if e.H > curH {
|
||
skyline = append(skyline, []int{e.X, e.H})
|
||
}
|
||
pq.Enque(e.N, e.H)
|
||
} else {
|
||
pq.Remove(e.N)
|
||
h := pq.Front()
|
||
if curH > h {
|
||
skyline = append(skyline, []int{e.X, h})
|
||
}
|
||
}
|
||
}
|
||
return skyline
|
||
}
|
||
|
||
// 扫面线伪代码
|
||
// events = {{x: L , height: H , type: entering},
|
||
// {x: R , height: H , type: leaving}}
|
||
// event.SortByX()
|
||
// ds = new DS()
|
||
|
||
// for e in events:
|
||
// if entering(e):
|
||
// if e.height > ds.max(): ans += [e.height]
|
||
// ds.add(e.height)
|
||
// if leaving(e):
|
||
// ds.remove(e.height)
|
||
// if e.height > ds.max(): ans += [ds.max()]
|
||
|
||
// E define
|
||
type E struct { // 定义一个 event 事件
|
||
N int // number 编号
|
||
X int // x 坐标
|
||
H int // height 高度
|
||
T int // type 0-进入 1-离开
|
||
}
|
||
|
||
// NewE define
|
||
func NewE(n, x, h, t int) E {
|
||
return E{
|
||
N: n,
|
||
X: x,
|
||
H: h,
|
||
T: t,
|
||
}
|
||
}
|
||
|
||
// IndexMaxPQ define
|
||
type IndexMaxPQ struct {
|
||
items []int
|
||
pq []int
|
||
qp []int
|
||
total int
|
||
}
|
||
|
||
// NewIndexMaxPQ define
|
||
func NewIndexMaxPQ(n int) IndexMaxPQ {
|
||
qp := make([]int, n)
|
||
for i := 0; i < n; i++ {
|
||
qp[i] = -1
|
||
}
|
||
return IndexMaxPQ{
|
||
items: make([]int, n),
|
||
pq: make([]int, n+1),
|
||
qp: qp,
|
||
}
|
||
}
|
||
|
||
// Enque define
|
||
func (q *IndexMaxPQ) Enque(key, val int) {
|
||
q.total++
|
||
q.items[key] = val
|
||
q.pq[q.total] = key
|
||
q.qp[key] = q.total
|
||
q.swim(q.total)
|
||
}
|
||
|
||
// Front define
|
||
func (q *IndexMaxPQ) Front() int {
|
||
if q.total < 1 {
|
||
return 0
|
||
}
|
||
return q.items[q.pq[1]]
|
||
}
|
||
|
||
// Remove define
|
||
func (q *IndexMaxPQ) Remove(key int) {
|
||
rank := q.qp[key]
|
||
q.exch(rank, q.total)
|
||
q.total--
|
||
q.qp[key] = -1
|
||
q.sink(rank)
|
||
}
|
||
|
||
func (q *IndexMaxPQ) sink(n int) {
|
||
for 2*n <= q.total {
|
||
k := 2 * n
|
||
if k < q.total && q.less(k, k+1) {
|
||
k++
|
||
}
|
||
if q.less(k, n) {
|
||
break
|
||
}
|
||
q.exch(k, n)
|
||
n = k
|
||
}
|
||
}
|
||
|
||
func (q *IndexMaxPQ) swim(n int) {
|
||
for n > 1 {
|
||
k := n / 2
|
||
if q.less(n, k) {
|
||
break
|
||
}
|
||
q.exch(n, k)
|
||
n = k
|
||
}
|
||
}
|
||
|
||
func (q *IndexMaxPQ) exch(i, j int) {
|
||
q.pq[i], q.pq[j] = q.pq[j], q.pq[i]
|
||
q.qp[q.pq[i]] = i
|
||
q.qp[q.pq[j]] = j
|
||
}
|
||
|
||
func (q *IndexMaxPQ) less(i, j int) bool {
|
||
return q.items[q.pq[i]] < q.items[q.pq[j]]
|
||
}
|