Skip to content

Commit 78497a2

Browse files
authored
feat: add swift implementation to lcof problem: No.41 (doocs#2922)
1 parent 6341e3b commit 78497a2

File tree

2 files changed

+229
-0
lines changed

2 files changed

+229
-0
lines changed

lcof/面试题41. 数据流中的中位数/README.md

+117
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,123 @@ public class MedianFinder {
412412
*/
413413
```
414414

415+
#### Swift
416+
417+
```swift
418+
class MedianFinder {
419+
private var lowerHalf = Heap<Int>(sort: >)
420+
private var upperHalf = Heap<Int>(sort: <)
421+
422+
init() {}
423+
424+
func addNum(_ num: Int) {
425+
if lowerHalf.count == 0 || num <= lowerHalf.peek()! {
426+
lowerHalf.insert(num)
427+
} else {
428+
upperHalf.insert(num)
429+
}
430+
431+
if lowerHalf.count > upperHalf.count + 1 {
432+
upperHalf.insert(lowerHalf.remove()!)
433+
} else if upperHalf.count > lowerHalf.count {
434+
lowerHalf.insert(upperHalf.remove()!)
435+
}
436+
}
437+
438+
func findMedian() -> Double {
439+
if lowerHalf.count > upperHalf.count {
440+
return Double(lowerHalf.peek()!)
441+
} else {
442+
return (Double(lowerHalf.peek()!) + Double(upperHalf.peek()!)) / 2.0
443+
}
444+
}
445+
}
446+
447+
struct Heap<T> {
448+
var elements: [T]
449+
let sort: (T, T) -> Bool
450+
451+
init(sort: @escaping (T, T) -> Bool) {
452+
self.sort = sort
453+
self.elements = []
454+
}
455+
456+
var count: Int {
457+
return elements.count
458+
}
459+
460+
func peek() -> T? {
461+
return elements.first
462+
}
463+
464+
mutating func insert(_ value: T) {
465+
elements.append(value)
466+
siftUp(from: elements.count - 1)
467+
}
468+
469+
mutating func remove() -> T? {
470+
guard !elements.isEmpty else { return nil }
471+
if elements.count == 1 {
472+
return elements.removeLast()
473+
} else {
474+
let value = elements[0]
475+
elements[0] = elements.removeLast()
476+
siftDown(from: 0)
477+
return value
478+
}
479+
}
480+
481+
private mutating func siftUp(from index: Int) {
482+
var child = index
483+
var parent = parentIndex(of: child)
484+
while child > 0 && sort(elements[child], elements[parent]) {
485+
elements.swapAt(child, parent)
486+
child = parent
487+
parent = self.parentIndex(of: child)
488+
}
489+
}
490+
491+
private mutating func siftDown(from index: Int) {
492+
var parent = index
493+
while true {
494+
let left = leftChildIndex(of: parent)
495+
let right = rightChildIndex(of: parent)
496+
var candidate = parent
497+
if left < elements.count && sort(elements[left], elements[candidate]) {
498+
candidate = left
499+
}
500+
if right < elements.count && sort(elements[right], elements[candidate]) {
501+
candidate = right
502+
}
503+
if candidate == parent {
504+
return
505+
}
506+
elements.swapAt(parent, candidate)
507+
parent = candidate
508+
}
509+
}
510+
511+
private func parentIndex(of index: Int) -> Int {
512+
return (index - 1) / 2
513+
}
514+
515+
private func leftChildIndex(of index: Int) -> Int {
516+
return 2 * index + 1
517+
}
518+
519+
private func rightChildIndex(of index: Int) -> Int {
520+
return 2 * index + 2
521+
}
522+
}
523+
524+
/**
525+
* Your MedianFinder object will be instantiated and called as such:
526+
* let obj = MedianFinder();
527+
* obj.addNum(num);
528+
* let param_2 = obj.findMedian();
529+
*/
530+
```
531+
415532
<!-- tabs:end -->
416533

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

0 commit comments

Comments
 (0)