Skip to content

Commit e71ee36

Browse files
committed
code update
1 parent de44998 commit e71ee36

File tree

2 files changed

+180
-22
lines changed

2 files changed

+180
-22
lines changed

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

+90-11
Original file line numberDiff line numberDiff line change
@@ -416,30 +416,109 @@ public class MedianFinder {
416416

417417
```swift
418418
class MedianFinder {
419-
private var lowerHalf = [Int]()
420-
private var upperHalf = [Int]()
419+
private var lowerHalf = Heap<Int>(sort: >)
420+
private var upperHalf = Heap<Int>(sort: <)
421421

422422
init() {}
423423

424424
func addNum(_ num: Int) {
425-
if lowerHalf.count > upperHalf.count {
426-
lowerHalf.append(num)
427-
lowerHalf.sort(by: >)
428-
upperHalf.append(lowerHalf.removeFirst())
425+
if lowerHalf.count == 0 || num <= lowerHalf.peek()! {
426+
lowerHalf.insert(num)
429427
} else {
430-
upperHalf.append(num)
431-
upperHalf.sort()
432-
lowerHalf.append(upperHalf.removeFirst())
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()!)
433435
}
434436
}
435437

436438
func findMedian() -> Double {
437439
if lowerHalf.count > upperHalf.count {
438-
return Double(lowerHalf.first!)
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()
439473
} else {
440-
return (Double(lowerHalf.first!) + Double(upperHalf.first!)) / 2.0
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
441508
}
442509
}
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+
}
443522
}
444523

445524
/**

lcof/面试题41. 数据流中的中位数/Solution.swift

+90-11
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,109 @@
11
class MedianFinder {
2-
private var lowerHalf = [Int]()
3-
private var upperHalf = [Int]()
2+
private var lowerHalf = Heap<Int>(sort: >)
3+
private var upperHalf = Heap<Int>(sort: <)
44

55
init() {}
66

77
func addNum(_ num: Int) {
8-
if lowerHalf.count > upperHalf.count {
9-
lowerHalf.append(num)
10-
lowerHalf.sort(by: >)
11-
upperHalf.append(lowerHalf.removeFirst())
8+
if lowerHalf.count == 0 || num <= lowerHalf.peek()! {
9+
lowerHalf.insert(num)
1210
} else {
13-
upperHalf.append(num)
14-
upperHalf.sort()
15-
lowerHalf.append(upperHalf.removeFirst())
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()!)
1618
}
1719
}
1820

1921
func findMedian() -> Double {
2022
if lowerHalf.count > upperHalf.count {
21-
return Double(lowerHalf.first!)
23+
return Double(lowerHalf.peek()!)
2224
} else {
23-
return (Double(lowerHalf.first!) + Double(upperHalf.first!)) / 2.0
25+
return (Double(lowerHalf.peek()!) + Double(upperHalf.peek()!)) / 2.0
2426
}
2527
}
2628
}
2729

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+
28107
/**
29108
* Your MedianFinder object will be instantiated and called as such:
30109
* let obj = MedianFinder();

0 commit comments

Comments
 (0)