Skip to content

Commit 33ee2c6

Browse files
authored
feat: add swift implementation to lcci problem: No.17.20 (#2807)
1 parent 2283a9e commit 33ee2c6

File tree

3 files changed

+321
-0
lines changed

3 files changed

+321
-0
lines changed

lcci/17.20.Continuous Median/README.md

+108
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,114 @@ func (h *hp) Pop() any {
189189
}
190190
```
191191

192+
```swift
193+
class MedianFinder {
194+
private var minHeap = Heap<Int>(sort: <)
195+
private var maxHeap = Heap<Int>(sort: >)
196+
197+
init() {
198+
}
199+
200+
func addNum(_ num: Int) {
201+
maxHeap.insert(num)
202+
minHeap.insert(maxHeap.remove()!)
203+
204+
if maxHeap.count < minHeap.count {
205+
maxHeap.insert(minHeap.remove()!)
206+
}
207+
}
208+
209+
func findMedian() -> Double {
210+
if maxHeap.count > minHeap.count {
211+
return Double(maxHeap.peek()!)
212+
}
213+
return (Double(maxHeap.peek()!) + Double(minHeap.peek()!)) / 2.0
214+
}
215+
}
216+
217+
struct Heap<T> {
218+
var elements: [T]
219+
let sort: (T, T) -> Bool
220+
221+
init(sort: @escaping (T, T) -> Bool, elements: [T] = []) {
222+
self.sort = sort
223+
self.elements = elements
224+
if !elements.isEmpty {
225+
for i in stride(from: elements.count / 2 - 1, through: 0, by: -1) {
226+
siftDown(from: i)
227+
}
228+
}
229+
}
230+
231+
var isEmpty: Bool {
232+
return elements.isEmpty
233+
}
234+
235+
var count: Int {
236+
return elements.count
237+
}
238+
239+
func peek() -> T? {
240+
return elements.first
241+
}
242+
243+
mutating func insert(_ value: T) {
244+
elements.append(value)
245+
siftUp(from: elements.count - 1)
246+
}
247+
248+
mutating func remove() -> T? {
249+
guard !elements.isEmpty else { return nil }
250+
elements.swapAt(0, elements.count - 1)
251+
let removedValue = elements.removeLast()
252+
siftDown(from: 0)
253+
return removedValue
254+
}
255+
256+
private mutating func siftUp(from index: Int) {
257+
var child = index
258+
var parent = parentIndex(ofChildAt: child)
259+
while child > 0 && sort(elements[child], elements[parent]) {
260+
elements.swapAt(child, parent)
261+
child = parent
262+
parent = parentIndex(ofChildAt: child)
263+
}
264+
}
265+
266+
private mutating func siftDown(from index: Int) {
267+
var parent = index
268+
while true {
269+
let left = leftChildIndex(ofParentAt: parent)
270+
let right = rightChildIndex(ofParentAt: parent)
271+
var candidate = parent
272+
if left < count && sort(elements[left], elements[candidate]) {
273+
candidate = left
274+
}
275+
if right < count && sort(elements[right], elements[candidate]) {
276+
candidate = right
277+
}
278+
if candidate == parent {
279+
return
280+
}
281+
elements.swapAt(parent, candidate)
282+
parent = candidate
283+
}
284+
}
285+
286+
private func parentIndex(ofChildAt index: Int) -> Int {
287+
return (index - 1) / 2
288+
}
289+
290+
private func leftChildIndex(ofParentAt index: Int) -> Int {
291+
return 2 * index + 1
292+
}
293+
294+
private func rightChildIndex(ofParentAt index: Int) -> Int {
295+
return 2 * index + 2
296+
}
297+
}
298+
```
299+
192300
<!-- tabs:end -->
193301

194302
<!-- end -->

lcci/17.20.Continuous Median/README_EN.md

+108
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,114 @@ func (h *hp) Pop() any {
185185
}
186186
```
187187

188+
```swift
189+
class MedianFinder {
190+
private var minHeap = Heap<Int>(sort: <)
191+
private var maxHeap = Heap<Int>(sort: >)
192+
193+
init() {
194+
}
195+
196+
func addNum(_ num: Int) {
197+
maxHeap.insert(num)
198+
minHeap.insert(maxHeap.remove()!)
199+
200+
if maxHeap.count < minHeap.count {
201+
maxHeap.insert(minHeap.remove()!)
202+
}
203+
}
204+
205+
func findMedian() -> Double {
206+
if maxHeap.count > minHeap.count {
207+
return Double(maxHeap.peek()!)
208+
}
209+
return (Double(maxHeap.peek()!) + Double(minHeap.peek()!)) / 2.0
210+
}
211+
}
212+
213+
struct Heap<T> {
214+
var elements: [T]
215+
let sort: (T, T) -> Bool
216+
217+
init(sort: @escaping (T, T) -> Bool, elements: [T] = []) {
218+
self.sort = sort
219+
self.elements = elements
220+
if !elements.isEmpty {
221+
for i in stride(from: elements.count / 2 - 1, through: 0, by: -1) {
222+
siftDown(from: i)
223+
}
224+
}
225+
}
226+
227+
var isEmpty: Bool {
228+
return elements.isEmpty
229+
}
230+
231+
var count: Int {
232+
return elements.count
233+
}
234+
235+
func peek() -> T? {
236+
return elements.first
237+
}
238+
239+
mutating func insert(_ value: T) {
240+
elements.append(value)
241+
siftUp(from: elements.count - 1)
242+
}
243+
244+
mutating func remove() -> T? {
245+
guard !elements.isEmpty else { return nil }
246+
elements.swapAt(0, elements.count - 1)
247+
let removedValue = elements.removeLast()
248+
siftDown(from: 0)
249+
return removedValue
250+
}
251+
252+
private mutating func siftUp(from index: Int) {
253+
var child = index
254+
var parent = parentIndex(ofChildAt: child)
255+
while child > 0 && sort(elements[child], elements[parent]) {
256+
elements.swapAt(child, parent)
257+
child = parent
258+
parent = parentIndex(ofChildAt: child)
259+
}
260+
}
261+
262+
private mutating func siftDown(from index: Int) {
263+
var parent = index
264+
while true {
265+
let left = leftChildIndex(ofParentAt: parent)
266+
let right = rightChildIndex(ofParentAt: parent)
267+
var candidate = parent
268+
if left < count && sort(elements[left], elements[candidate]) {
269+
candidate = left
270+
}
271+
if right < count && sort(elements[right], elements[candidate]) {
272+
candidate = right
273+
}
274+
if candidate == parent {
275+
return
276+
}
277+
elements.swapAt(parent, candidate)
278+
parent = candidate
279+
}
280+
}
281+
282+
private func parentIndex(ofChildAt index: Int) -> Int {
283+
return (index - 1) / 2
284+
}
285+
286+
private func leftChildIndex(ofParentAt index: Int) -> Int {
287+
return 2 * index + 1
288+
}
289+
290+
private func rightChildIndex(ofParentAt index: Int) -> Int {
291+
return 2 * index + 2
292+
}
293+
}
294+
```
295+
188296
<!-- tabs:end -->
189297

190298
<!-- end -->
+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
class MedianFinder {
2+
private var minHeap = Heap<Int>(sort: <)
3+
private var maxHeap = Heap<Int>(sort: >)
4+
5+
init() {
6+
}
7+
8+
func addNum(_ num: Int) {
9+
maxHeap.insert(num)
10+
minHeap.insert(maxHeap.remove()!)
11+
12+
if maxHeap.count < minHeap.count {
13+
maxHeap.insert(minHeap.remove()!)
14+
}
15+
}
16+
17+
func findMedian() -> Double {
18+
if maxHeap.count > minHeap.count {
19+
return Double(maxHeap.peek()!)
20+
}
21+
return (Double(maxHeap.peek()!) + Double(minHeap.peek()!)) / 2.0
22+
}
23+
}
24+
25+
struct Heap<T> {
26+
var elements: [T]
27+
let sort: (T, T) -> Bool
28+
29+
init(sort: @escaping (T, T) -> Bool, elements: [T] = []) {
30+
self.sort = sort
31+
self.elements = elements
32+
if !elements.isEmpty {
33+
for i in stride(from: elements.count / 2 - 1, through: 0, by: -1) {
34+
siftDown(from: i)
35+
}
36+
}
37+
}
38+
39+
var isEmpty: Bool {
40+
return elements.isEmpty
41+
}
42+
43+
var count: Int {
44+
return elements.count
45+
}
46+
47+
func peek() -> T? {
48+
return elements.first
49+
}
50+
51+
mutating func insert(_ value: T) {
52+
elements.append(value)
53+
siftUp(from: elements.count - 1)
54+
}
55+
56+
mutating func remove() -> T? {
57+
guard !elements.isEmpty else { return nil }
58+
elements.swapAt(0, elements.count - 1)
59+
let removedValue = elements.removeLast()
60+
siftDown(from: 0)
61+
return removedValue
62+
}
63+
64+
private mutating func siftUp(from index: Int) {
65+
var child = index
66+
var parent = parentIndex(ofChildAt: child)
67+
while child > 0 && sort(elements[child], elements[parent]) {
68+
elements.swapAt(child, parent)
69+
child = parent
70+
parent = parentIndex(ofChildAt: child)
71+
}
72+
}
73+
74+
private mutating func siftDown(from index: Int) {
75+
var parent = index
76+
while true {
77+
let left = leftChildIndex(ofParentAt: parent)
78+
let right = rightChildIndex(ofParentAt: parent)
79+
var candidate = parent
80+
if left < count && sort(elements[left], elements[candidate]) {
81+
candidate = left
82+
}
83+
if right < 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(ofChildAt index: Int) -> Int {
95+
return (index - 1) / 2
96+
}
97+
98+
private func leftChildIndex(ofParentAt index: Int) -> Int {
99+
return 2 * index + 1
100+
}
101+
102+
private func rightChildIndex(ofParentAt index: Int) -> Int {
103+
return 2 * index + 2
104+
}
105+
}

0 commit comments

Comments
 (0)