★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公衆號:山青詠芝(shanqingyongzhi)
➤博客園地址:山青詠芝(https://www.cnblogs.com/strengthen/)
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址:http://www.javashuo.com/article/p-nwjnnbix-md.html
➤若是連接不是山青詠芝的博客園地址,則多是爬取做者的文章。
➤原文已修改更新!強烈建議點擊原文地址閱讀!支持做者!支持原創!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★html
A city's skyline is the outer contour of the silhouette formed by all the buildings in that city when viewed from a distance. Now suppose you are given the locations and height of all the buildings as shown on a cityscape photo (Figure A), write a program to output the skylineformed by these buildings collectively (Figure B).node
The geometric information of each building is represented by a triplet of integers [Li, Ri, Hi]
, where Li
and Ri
are the x coordinates of the left and right edge of the ith building, respectively, and Hi
is its height. It is guaranteed that 0 ≤ Li, Ri ≤ INT_MAX
, 0 < Hi ≤ INT_MAX
, and Ri - Li > 0
. You may assume all buildings are perfect rectangles grounded on an absolutely flat surface at height 0.git
For instance, the dimensions of all buildings in Figure A are recorded as: [ [2 9 10], [3 7 15], [5 12 12], [15 20 10], [19 24 8] ]
.github
The output is a list of "key points" (red dots in Figure B) in the format of [ [x1,y1], [x2, y2], [x3, y3], ... ]
that uniquely defines a skyline. A key point is the left endpoint of a horizontal line segment. Note that the last key point, where the rightmost building ends, is merely used to mark the termination of the skyline, and always has zero height. Also, the ground in between any two adjacent buildings should be considered part of the skyline contour.api
For instance, the skyline in Figure B should be represented as:[ [2 10], [3 15], [7 12], [12 0], [15 10], [20 8], [24, 0] ]
.微信
Notes:app
[0, 10000]
.Li
.[...[2 3], [4 5], [7 5], [11 5], [12 7]...]
is not acceptable; the three lines of height 5 should be merged into one in the final output as such: [...[2 3], [4 5], [12 7], ...]
城市的天際線是從遠處觀看該城市中全部建築物造成的輪廓的外部輪廓。如今,假設您得到了城市風光照片(圖A)上顯示的全部建築物的位置和高度,請編寫一個程序以輸出由這些建築物造成的天際線(圖B)。ide
每一個建築物的幾何信息用三元組 [Li,Ri,Hi]
表示,其中 Li
和 Ri
分別是第 i 座建築物左右邊緣的 x 座標,Hi
是其高度。能夠保證 0 ≤ Li, Ri ≤ INT_MAX
, 0 < Hi ≤ INT_MAX
和 Ri - Li > 0
。您能夠假設全部建築物都是在絕對平坦且高度爲 0 的表面上的完美矩形。ui
例如,圖A中全部建築物的尺寸記錄爲:[ [2 9 10], [3 7 15], [5 12 12], [15 20 10], [19 24 8] ]
。spa
輸出是以 [ [x1,y1], [x2, y2], [x3, y3], ... ]
格式的「關鍵點」(圖B中的紅點)的列表,它們惟一地定義了天際線。關鍵點是水平線段的左端點。請注意,最右側建築物的最後一個關鍵點僅用於標記天際線的終點,並始終爲零高度。此外,任何兩個相鄰建築物之間的地面都應被視爲天際線輪廓的一部分。
例如,圖B中的天際線應該表示爲:[ [2 10], [3 15], [7 12], [12 0], [15 10], [20 8], [24, 0] ]
。
說明:
[0, 10000]
範圍內。Li
。[...[2 3], [4 5], [7 5], [11 5], [12 7]...]
是不正確的答案;三條高度爲 5 的線應該在最終輸出中合併爲一個:[...[2 3], [4 5], [12 7], ...]
264ms
1 class Solution { 2 func getSkyline(_ buildings: [[Int]]) -> [[Int]] { 3 var queue = [[Int]]() 4 for building in buildings { 5 let begin = [building[0],building[2]] 6 let end = [building[1], -building[2]] 7 queue.append(begin) 8 queue.append(end) 9 } 10 11 queue.sort { (nums1, nums2) -> Bool in 12 if nums1[0] == nums2[0] { 13 return nums1[1] > nums2[1] 14 } 15 16 return nums1[0] < nums2[0] 17 } 18 19 20 var res = [[Int]]() 21 var heights = Heap(array: [Int](), sort: >) 22 var removes = Heap(array: [Int](), sort: >) 23 var pHeight = 0 24 for line in queue { 25 let h = line[1] 26 27 if h > 0 { 28 if h > pHeight { 29 res.append([line[0],h]) 30 } 31 heights.insert(h) 32 pHeight = heights.peek()! 33 }else { 34 removes.insert(-h) 35 while !heights.isEmpty && !removes.isEmpty && heights.peek()! == removes.peek()! { 36 heights.remove() 37 removes.remove() 38 } 39 pHeight = heights.peek() ?? 0 40 if -h > pHeight { 41 res.append([line[0],pHeight]) 42 } 43 } 44 } 45 return res 46 } 47 48 public struct Heap<T> { 49 var nodes = [T]() 50 51 private var orderCriteria:(T,T) -> Bool 52 53 public init(sort:@escaping (T,T) -> Bool) { 54 self.orderCriteria = sort 55 } 56 57 public init(array:[T],sort:@escaping(T, T) -> Bool) { 58 self.orderCriteria = sort 59 configureHeap(from:array) 60 } 61 62 private mutating func configureHeap(from array:[T]) { 63 nodes = array 64 for i in stride(from: (nodes.count - 1) / 2, through: 0, by: -1) { 65 shiftDown(i) 66 } 67 } 68 69 public var isEmpty:Bool { 70 return nodes.isEmpty 71 } 72 73 public var count : Int { 74 return nodes.count 75 } 76 77 @inline(__always) internal func parentIndex(ofIndex i : Int) -> Int { 78 return (i - 1) / 2 79 } 80 81 @inline(__always) internal func leftChildIndex(ofIndex i : Int) -> Int { 82 return 2 * i + 1 83 } 84 85 @inline(__always) internal func rightChildIndex(ofIndex i : Int) -> Int { 86 return 2 * i + 2 87 } 88 89 public func peek() -> T? { 90 return nodes.first 91 } 92 93 public mutating func insert(_ value: T) { 94 nodes.append(value) 95 shiftUp(nodes.count - 1) 96 } 97 98 public mutating func insert<S:Sequence>(_ sequence: S) where S.Iterator.Element == T { 99 for value in sequence { 100 insert(value) 101 } 102 } 103 104 @discardableResult public mutating func remove() -> T? { 105 guard !isEmpty else {return nil} 106 if nodes.count == 1 { 107 return nodes.removeFirst() 108 }else { 109 let value = nodes[0] 110 nodes[0] = nodes.removeLast() 111 shiftDown(0) 112 return value 113 } 114 } 115 116 117 @discardableResult public mutating func remove(at index: Int) -> T? { 118 guard index < count else {return nil} 119 120 let size = nodes.count - 1 121 if index != count { 122 nodes.swapAt(index, size) 123 shiftDown(form: index, until: size) 124 shiftUp(index) 125 } 126 127 return nodes.removeLast() 128 129 } 130 131 internal mutating func shiftUp(_ index : Int) { 132 var childIndex = index 133 let child = nodes[childIndex] 134 var parentIndex = self.parentIndex(ofIndex: childIndex) 135 136 while childIndex > 0 && orderCriteria(child, nodes[parentIndex]) { 137 nodes[childIndex] = nodes[parentIndex] 138 childIndex = parentIndex 139 parentIndex = self.parentIndex(ofIndex: childIndex) 140 } 141 nodes[childIndex] = child 142 } 143 144 internal mutating func shiftDown(form index: Int, until endIndex: Int) { 145 let leftChildIndex = self.leftChildIndex(ofIndex: index) 146 let rightChildIndex = leftChildIndex + 1 147 var first = index 148 if leftChildIndex < endIndex && orderCriteria(nodes[leftChildIndex], nodes[first]) { 149 first = leftChildIndex 150 } 151 152 if rightChildIndex < endIndex && orderCriteria(nodes[rightChildIndex], nodes[first]) { 153 first = rightChildIndex 154 } 155 if first == index {return} 156 nodes.swapAt(index, first) 157 shiftDown(form: first, until: endIndex) 158 } 159 160 internal mutating func shiftDown(_ index:Int) { 161 162 shiftDown(form: index, until: nodes.count) 163 } 164 165 } 166 }
676ms
1 class Solution { 2 func getSkyline(_ buildings: [[Int]]) -> [[Int]] { 3 var points: [Int] = [] 4 for building in buildings { 5 points.append(building[0]) 6 points.append(building[1]) 7 } 8 points.sort() 9 10 var segs = [Int](repeating: 0, count: points.count) 11 12 var pos = 0 13 for building in buildings { 14 // find start point 15 while points[pos] < building[0] { pos += 1 } 16 // go to end 17 var i = pos 18 19 while points[i] < building[1] { 20 if segs[i] < building[2] { 21 segs[i] = building[2] 22 } 23 i += 1 24 } 25 } 26 27 var result: [[Int]] = [] 28 var currHeight = 0 29 for (index, h) in segs.enumerated() { 30 if currHeight != h { 31 result.append([points[index], h]) 32 currHeight = h 33 } 34 } 35 36 return result 37 } 38 }
1660ms
1 class Solution { 2 public struct PriorityQueue<T: Comparable> { 3 4 fileprivate var heap = [T]() 5 private let ordered: (T, T) -> Bool 6 7 public init(ascending: Bool = false, startingValues: [T] = []) { 8 self.init(order: ascending ? { $0 > $1 } : { $0 < $1 }, startingValues: startingValues) 9 } 10 11 /// Creates a new PriorityQueue with the given ordering. 12 /// 13 /// - parameter order: A function that specifies whether its first argument should 14 /// come after the second argument in the PriorityQueue. 15 /// - parameter startingValues: An array of elements to initialize the PriorityQueue with. 16 public init(order: @escaping (T, T) -> Bool, startingValues: [T] = []) { 17 ordered = order 18 19 // Based on "Heap construction" from Sedgewick p 323 20 heap = startingValues 21 var i = heap.count/2 - 1 22 while i >= 0 { 23 sink(i) 24 i -= 1 25 } 26 } 27 28 /// How many elements the Priority Queue stores 29 public var count: Int { return heap.count } 30 31 /// true if and only if the Priority Queue is empty 32 public var isEmpty: Bool { return heap.isEmpty } 33 34 /// Add a new element onto the Priority Queue. O(lg n) 35 /// 36 /// - parameter element: The element to be inserted into the Priority Queue. 37 public mutating func push(_ element: T) { 38 heap.append(element) 39 swim(heap.count - 1) 40 } 41 42 /// Remove and return the element with the highest priority (or lowest if ascending). O(lg n) 43 /// 44 /// - returns: The element with the highest priority in the Priority Queue, or nil if the PriorityQueue is empty. 45 public mutating func pop() -> T? { 46 47 if heap.isEmpty { return nil } 48 if heap.count == 1 { return heap.removeFirst() } // added for Swift 2 compatibility 49 // so as not to call swap() with two instances of the same location 50 heap.swapAt(0, heap.count - 1) 51 let temp = heap.removeLast() 52 sink(0) 53 54 return temp 55 } 56 57 58 /// Removes the first occurence of a particular item. Finds it by value comparison using ==. O(n) 59 /// Silently exits if no occurrence found. 60 /// 61 /// - parameter item: The item to remove the first occurrence of. 62 public mutating func remove(_ item: T) { 63 if let index = heap.index(of: item) { 64 heap.swapAt(index, heap.count - 1) 65 heap.removeLast() 66 if index < heap.count { // if we removed the last item, nothing to swim 67 swim(index) 68 sink(index) 69 } 70 } 71 } 72 73 /// Removes all occurences of a particular item. Finds it by value comparison using ==. O(n) 74 /// Silently exits if no occurrence found. 75 /// 76 /// - parameter item: The item to remove. 77 public mutating func removeAll(_ item: T) { 78 var lastCount = heap.count 79 remove(item) 80 while (heap.count < lastCount) { 81 lastCount = heap.count 82 remove(item) 83 } 84 } 85 86 /// Get a look at the current highest priority item, without removing it. O(1) 87 /// 88 /// - returns: The element with the highest priority in the PriorityQueue, or nil if the PriorityQueue is empty. 89 public func peek() -> T? { 90 return heap.first 91 } 92 93 /// Eliminate all of the elements from the Priority Queue. 94 public mutating func clear() { 95 heap.removeAll(keepingCapacity: false) 96 } 97 98 // Based on example from Sedgewick p 316 99 private mutating func sink(_ index: Int) { 100 var index = index 101 while 2 * index + 1 < heap.count { 102 103 var j = 2 * index + 1 104 105 if j < (heap.count - 1) && ordered(heap[j], heap[j + 1]) { j += 1 } 106 if !ordered(heap[index], heap[j]) { break } 107 108 heap.swapAt(index, j) 109 index = j 110 } 111 } 112 113 // Based on example from Sedgewick p 316 114 private mutating func swim(_ index: Int) { 115 var index = index 116 while index > 0 && ordered(heap[(index - 1) / 2], heap[index]) { 117 heap.swapAt((index - 1) / 2, index) 118 index = (index - 1) / 2 119 } 120 } 121 } 122 123 func getSkyline(_ buildings: [[Int]]) -> [[Int]] { 124 var heights: [(pos: Int, h: Int)] = [] 125 for building in buildings { 126 heights.append((building[0], -building[2])) 127 heights.append((building[1], building[2])) 128 } 129 heights.sort { (a, b) in 130 if (a.pos == b.pos) { 131 return a.h < b.h 132 } else { 133 return a.pos < b.pos 134 } 135 } 136 137 var heap = PriorityQueue<Int>() 138 var result: [[Int]] = [] 139 var prev = 0 140 141 heap.push(0) 142 for h in heights { 143 if (h.h < 0) { 144 heap.push(-h.h) 145 } else { 146 heap.remove(h.h) 147 } 148 if let curr = heap.peek(), prev != curr { 149 result.append([h.pos, curr]) 150 prev = curr 151 } 152 } 153 154 return result 155 } 156 }
1712ms
1 class PriorityQueue<T> { 2 private var heap: [T] = [T]() 3 private let ordered: (T, T) -> Bool 4 5 init(order: @escaping (T, T) -> Bool) { 6 self.ordered = order 7 } 8 9 var isEmpty: Bool { 10 return heap.isEmpty 11 } 12 var count: Int { 13 return heap.count 14 } 15 16 func push(_ element: T) { 17 heap.append(element) 18 swim(heap.count - 1) 19 } 20 21 func pop() -> T? { 22 if self.isEmpty { 23 return nil 24 } 25 26 if self.heap.count == 1 { 27 return heap.remove(at: 0) 28 } 29 30 heap.swapAt(0, heap.count - 1) 31 let temp = heap.removeLast() 32 sink(0) 33 return temp 34 } 35 36 func peek() -> T? { 37 if self.isEmpty { 38 return nil 39 } 40 41 return self.heap[0] 42 } 43 44 private func sink(_ index: Int) { 45 var index = index 46 while 2 * index + 1 < heap.count { 47 let leftChildIndex = 2 * index + 1 48 49 var first = index 50 if leftChildIndex < heap.count && ordered(heap[leftChildIndex], heap[first]) { 51 first = leftChildIndex 52 } 53 54 let rightChildIndex = leftChildIndex + 1 55 if rightChildIndex < heap.count && ordered(heap[rightChildIndex], heap[first]) { 56 first = rightChildIndex 57 } 58 59 if index == first { 60 break 61 } 62 63 heap.swapAt(index, first) 64 index = first 65 } 66 } 67 68 private func swim(_ index: Int) { 69 var index = index 70 while index > 0 && ordered(heap[index], heap[(index - 1) / 2]) { 71 heap.swapAt((index - 1) / 2, index) 72 index = (index - 1) / 2 73 } 74 } 75 } 76 77 extension PriorityQueue where T: Comparable { 78 func remove(_ element: T) { 79 if let index = heap.index(of: element) { 80 heap.swapAt(index, heap.count - 1) 81 heap.removeLast() 82 if index < heap.count { 83 swim(index) 84 sink(index) 85 } 86 } 87 } 88 } 89 90 class Solution { 91 class Point { 92 var pos: Int 93 var height: Int 94 var isStart: Bool 95 96 init(_ pos: Int, _ height: Int, _ isStart: Bool) { 97 self.pos = pos 98 self.height = height 99 self.isStart = isStart 100 } 101 } 102 103 func getSkyline(_ buildings: [[Int]]) -> [[Int]] { 104 guard buildings.count > 0 && buildings[0].count > 0 else { 105 return [] 106 } 107 108 var positions = Array(repeating: Point(0, 0, false), count: buildings.count * 2) 109 for idx in 0 ..< buildings.count { 110 let start = Point(buildings[idx][0], buildings[idx][2], true) 111 positions[idx * 2] = start 112 113 let end = Point(buildings[idx][1], buildings[idx][2], false) 114 positions[idx * 2 + 1] = end 115 } 116 117 positions.sort { pt1, pt2 in 118 if pt1.pos != pt2.pos { 119 return pt1.pos < pt2.pos 120 } 121 122 if pt1.isStart && pt2.isStart { 123 return pt1.height > pt2.height 124 } 125 126 if !pt1.isStart && !pt2.isStart { 127 return pt1.height < pt2.height 128 } 129 130 return pt1.isStart 131 } 132 133 let queue = PriorityQueue<Int>(order: >) 134 queue.push(0) 135 136 var result: [[Int]] = [] 137 var preMaxVal = 0 138 for point in positions { 139 if point.isStart { 140 queue.push(point.height) 141 let curMaxVal = queue.peek()! 142 if curMaxVal > preMaxVal { 143 result.append([point.pos, point.height]) 144 preMaxVal = curMaxVal 145 } 146 } else { 147 queue.remove(point.height) 148 let curMaxVal = queue.peek()! 149 if curMaxVal < preMaxVal { 150 result.append([point.pos, curMaxVal]) 151 preMaxVal = curMaxVal 152 } 153 } 154 } 155 156 return result 157 } 158 }
1916ms
1 class Solution { 2 func getSkyline(_ buildings: [[Int]]) -> [[Int]] { 3 if buildings.count == 0 { 4 return [] 5 } 6 if buildings.count == 1 { 7 let b = buildings[0] 8 let x1 = b[0]; let x2 = b[1]; let y = b[2] 9 return [[x1, y], [x2, 0]] 10 } 11 var bsplit: [(Int, Int, Bool)] = [] 12 for b in buildings { 13 let x1 = b[0]; let x2 = b[1]; let y = b[2] 14 bsplit.append((x1, y, false)) 15 bsplit.append((x2, y, true)) 16 } 17 // TODO replace h with priority queue 18 var h: [(Int, Int)] = [] 19 let s1: ((Int, Int), (Int, Int)) -> Bool = { 20 $0.1 > $1.1 21 || ($0.1 == $1.1 && $0.0 > $0.1) 22 } 23 let so: ((Int, Int, Bool), (Int, Int, Bool)) -> Bool = { 24 $0.0 < $1.0 25 || ($0.0 == $1.0 && $0.2 == false && $1.2 == true) 26 || ($0.0 == $1.0 && $0.1 > $1.1) 27 } 28 let buildingsSorted = bsplit.sorted(by: so) 29 // print("buildingsSorted \(buildingsSorted)") 30 var ans: [[Int]] = [] 31 for i in 0..<buildingsSorted.count { 32 let b = buildingsSorted[i] 33 let bx = b.0; let by = b.1; let close = b.2 == true 34 // print("b \(b) h \(h)") 35 if h.count == 0 { 36 h.append((bx, by)) 37 ans.append([bx, by]) 38 continue 39 } 40 if close { 41 if let index = h.firstIndex(where: {$0.1 == by}) { 42 h.remove(at: index) 43 if h.count == 0 { ans.append([bx, 0]) } 44 if let l = h.first { 45 if l.1 < by { ans.append([bx, l.1]) } 46 } 47 } 48 continue 49 } 50 // print("b \(b) h \(h)") 51 if let l = h.first { 52 if l.1 < by { ans.append([bx, by]) } 53 // print("l.1 \(l.1) by \(by) x3 ans \(ans)") 54 } 55 if let index = h.firstIndex(where: { $0.1 < by }) { 56 h.insert((bx, by), at:index) 57 } else { 58 h.append((bx, by)) 59 } 60 /* 61 h.append((bx, by)) 62 h.sort(by: s1) // need to optimize??? 63 */ 64 // print("hx \(h)") 65 } 66 // print("ans \(ans)") 67 var i = 1 68 while i < ans.count { 69 // print("i \(i) ans \(ans)") 70 if ans[i][0] == ans[i-1][0] { 71 ans.remove(at: i - 1) 72 continue 73 } 74 i += 1 75 } 76 return ans 77 } 78 }