The Skyline Problem Solutions in Go
Number 218
Difficulty Hard
Acceptance 34.6%
Link LeetCode
Other languages C++
Solutions
Go solution by halfrost/LeetCode-Go
package leetcodeimport ("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, falseposMap, 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-- enterel := NewE(i, l, h, 0)es = append(es, el)// 0 -- leaveer := 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 definetype E struct { // 定义一个 event 事件N int // number 编号X int // x 坐标H int // height 高度T int // type 0-进入 1-离开}// NewE definefunc NewE(n, x, h, t int) E {return E{N: n,X: x,H: h,T: t,}}// IndexMaxPQ definetype IndexMaxPQ struct {items []intpq []intqp []inttotal int}// NewIndexMaxPQ definefunc 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 definefunc (q *IndexMaxPQ) Enque(key, val int) {q.total++q.items[key] = valq.pq[q.total] = keyq.qp[key] = q.totalq.swim(q.total)}// Front definefunc (q *IndexMaxPQ) Front() int {if q.total < 1 {return 0}return q.items[q.pq[1]]}// Remove definefunc (q *IndexMaxPQ) Remove(key int) {rank := q.qp[key]q.exch(rank, q.total)q.total--q.qp[key] = -1q.sink(rank)}func (q *IndexMaxPQ) sink(n int) {for 2*n <= q.total {k := 2 * nif 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 / 2if 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]] = iq.qp[q.pq[j]] = j}func (q *IndexMaxPQ) less(i, j int) bool {return q.items[q.pq[i]] < q.items[q.pq[j]]}