1+ class Solution {
2+ func kthLargestNumber( _ nums: [ String ] , _ k: Int ) -> String {
3+ // Use a Min Heap for storing upto k-elements max in the priority queue
4+ var heap : Heap < String > = Heap ( sort: { ( str1, str2) in
5+ guard str1. count== str2. countelse { return str1. count< str2. count}
6+ for (c1, c2) in zip ( str1, str2) {
7+ guard c1== c2else { return c1< c2}
8+ }
9+ return false
10+ } )
11+
12+ nums. forEach { numin
13+ heap. insert ( num)
14+ if heap. count> k{
15+ heap. remove ( )
16+ }
17+ }
18+
19+ return heap. peek ( ) ?? " "
20+ }
21+ }
22+
23+ // Heap used from https://github.com/kodecocodes/swift-algorithm-club/blob/master/Heap/Heap.swift
24+ public struct Heap < T> {
25+ var nodes = [ T] ( )
26+
27+ private var orderCriteria : ( T , T ) -> Bool
28+
29+ public init ( sort: @escaping ( T , T ) -> Bool ) {
30+ self . orderCriteria= sort
31+ }
32+
33+ public init ( array: [ T ] , sort: @escaping ( T , T ) -> Bool ) {
34+ self . orderCriteria= sort
35+ configureHeap ( from: array)
36+ }
37+
38+ private mutating func configureHeap( from array: [ T ] ) {
39+ nodes= array
40+ for i in stride ( from: ( nodes. count/ 2 - 1 ) , through: 0 , by: - 1 ) {
41+ shiftDown ( i)
42+ }
43+ }
44+
45+ public var isEmpty : Bool {
46+ return nodes. isEmpty
47+ }
48+
49+ public var count : Int {
50+ return nodes. count
51+ }
52+
53+ @inline ( __always) internal func parentIndex( ofIndex i: Int ) -> Int {
54+ return ( i- 1 ) / 2
55+ }
56+
57+ @inline ( __always) internal func leftChildIndex( ofIndex i: Int ) -> Int {
58+ return 2 * i+ 1
59+ }
60+
61+ @inline ( __always) internal func rightChildIndex( ofIndex i: Int ) -> Int {
62+ return 2 * i+ 2
63+ }
64+
65+ public func peek( ) -> T ? {
66+ return nodes. first
67+ }
68+
69+ public mutating func insert( _ value: T ) {
70+ nodes. append ( value)
71+ shiftUp ( nodes. count- 1 )
72+ }
73+
74+ public mutating func insert< S: Sequence > ( _ sequence: S ) where S. Iterator. Element== T {
75+ for value in sequence{
76+ insert ( value)
77+ }
78+ }
79+
80+ public mutating func replace( index i: Int , value: T ) {
81+ guard i< nodes. countelse { return }
82+ remove ( at: i)
83+ insert ( value)
84+ }
85+
86+ @discardableResult public mutating func remove( ) -> T ? {
87+ guard !nodes. isEmptyelse { return nil }
88+ if nodes. count== 1 {
89+ return nodes. removeLast ( )
90+ } else {
91+ let value = nodes [ 0 ]
92+ nodes [ 0 ] = nodes. removeLast ( )
93+ shiftDown ( 0 )
94+ return value
95+ }
96+ }
97+
98+ @discardableResult public mutating func remove( at index: Int ) -> T ? {
99+ guard index< nodes. countelse { return nil }
100+ let size = nodes. count- 1
101+ if index!= size{
102+ nodes. swapAt ( index, size)
103+ shiftDown ( from: index, until: size)
104+ shiftUp ( index)
105+ }
106+ return nodes. removeLast ( )
107+ }
108+
109+ internal mutating func shiftUp( _ index: Int ) {
110+ var childIndex = index
111+ let child = nodes [ childIndex]
112+ var parentIndex = self . parentIndex ( ofIndex: childIndex)
113+
114+ while childIndex> 0 &&orderCriteria ( child, nodes [ parentIndex] ) {
115+ nodes [ childIndex] = nodes [ parentIndex]
116+ childIndex= parentIndex
117+ parentIndex= self . parentIndex ( ofIndex: childIndex)
118+ }
119+
120+ nodes [ childIndex] = child
121+ }
122+
123+ internal mutating func shiftDown( from index: Int , until endIndex: Int ) {
124+ let leftChildIndex = self . leftChildIndex ( ofIndex: index)
125+ let rightChildIndex = leftChildIndex+ 1
126+
127+ var first = index
128+ if leftChildIndex< endIndex &&orderCriteria ( nodes [ leftChildIndex] , nodes [ first] ) {
129+ first= leftChildIndex
130+ }
131+ if rightChildIndex< endIndex &&orderCriteria ( nodes [ rightChildIndex] , nodes [ first] ) {
132+ first= rightChildIndex
133+ }
134+ if first== index{ return }
135+
136+ nodes. swapAt ( index, first)
137+ shiftDown ( from: first, until: endIndex)
138+ }
139+
140+ internal mutating func shiftDown( _ index: Int ) {
141+ shiftDown ( from: index, until: nodes. count)
142+ }
143+ }