-
-
Notifications
You must be signed in to change notification settings - Fork 8.9k
/
Copy pathSolution.swift
111 lines (95 loc) · 2.82 KB
/
Solution.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
class MedianFinder {
private var minQ = Heap<Int>(sort: <)
private var maxQ = Heap<Int>(sort: >)
init() {
}
func addNum(_ num: Int) {
maxQ.insert(num)
minQ.insert(maxQ.remove()!)
if maxQ.count < minQ.count {
maxQ.insert(minQ.remove()!)
}
}
func findMedian() -> Double {
if maxQ.count > minQ.count {
return Double(maxQ.peek()!)
}
return (Double(maxQ.peek()!) + Double(minQ.peek()!)) / 2.0
}
}
struct Heap<T> {
var elements: [T]
let sort: (T, T) -> Bool
init(sort: @escaping (T, T) -> Bool, elements: [T] = []) {
self.sort = sort
self.elements = elements
if !elements.isEmpty {
for i in stride(from: elements.count / 2 - 1, through: 0, by: -1) {
siftDown(from: i)
}
}
}
var isEmpty: Bool {
return elements.isEmpty
}
var count: Int {
return elements.count
}
func peek() -> T? {
return elements.first
}
mutating func insert(_ value: T) {
elements.append(value)
siftUp(from: elements.count - 1)
}
mutating func remove() -> T? {
guard !elements.isEmpty else { return nil }
elements.swapAt(0, elements.count - 1)
let removedValue = elements.removeLast()
siftDown(from: 0)
return removedValue
}
private mutating func siftUp(from index: Int) {
var child = index
var parent = parentIndex(ofChildAt: child)
while child > 0 && sort(elements[child], elements[parent]) {
elements.swapAt(child, parent)
child = parent
parent = parentIndex(ofChildAt: child)
}
}
private mutating func siftDown(from index: Int) {
var parent = index
while true {
let left = leftChildIndex(ofParentAt: parent)
let right = rightChildIndex(ofParentAt: parent)
var candidate = parent
if left < count && sort(elements[left], elements[candidate]) {
candidate = left
}
if right < count && sort(elements[right], elements[candidate]) {
candidate = right
}
if candidate == parent {
return
}
elements.swapAt(parent, candidate)
parent = candidate
}
}
private func parentIndex(ofChildAt index: Int) -> Int {
return (index - 1) / 2
}
private func leftChildIndex(ofParentAt index: Int) -> Int {
return 2 * index + 1
}
private func rightChildIndex(ofParentAt index: Int) -> Int {
return 2 * index + 2
}
}
/**
* Your MedianFinder object will be instantiated and called as such:
* let obj = MedianFinder()
* obj.addNum(num)
* let ret_2: Double = obj.findMedian()
*/