[Swift]LeetCode857. 雇佣 K 名工人的最低成本 | Minimum Cost to Hire K Workers
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公众号:山青咏芝(shanqingyongzhi)
➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/)
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址: https://www.cnblogs.com/strengthen/p/10594768.html
➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
There are N
workers. The i
-th worker has a quality[i]
and a minimum wage expectation wage[i]
.
Now we want to hire exactly K
workers to form a paid group. When hiring a group of K workers, we must pay them according to the following rules:
- Every worker in the paid group should be paid in the ratio of their quality compared to other workers in the paid group.
- Every worker in the paid group must be paid at least their minimum wage expectation.
Return the least amount of money needed to form a paid group satisfying the above conditions.
Example 1:
Input: quality = [10,20,5], wage = [70,50,30], K = 2
Output: 105.00000
Explanation: We pay 70 to 0-th worker and 35 to 2-th worker.
Example 2:
Input: quality = [3,1,10,10,1], wage = [4,8,2,2,7], K = 3
Output: 30.66667
Explanation: We pay 4 to 0-th worker, 13.33333 to 2-th and 3-th workers seperately.
Note:
1 <= K <= N <= 10000
, whereN = quality.length = wage.length
1 <= quality[i] <= 10000
1 <= wage[i] <= 10000
- Answers within
10^-5
of the correct answer will be considered correct.
有 N
名工人。 第 i
名工人的工作质量为 quality[i]
,其最低期望工资为 wage[i]
。
现在我们想雇佣 K
名工人组成一个工资组。在雇佣 一组 K 名工人时,我们必须按照下述规则向他们支付工资:
- 对工资组中的每名工人,应当按其工作质量与同组其他工人的工作质量的比例来支付工资。
- 工资组中的每名工人至少应当得到他们的最低期望工资。
返回组成一个满足上述条件的工资组至少需要多少钱。
示例 1:
输入: quality = [10,20,5], wage = [70,50,30], K = 2 输出: 105.00000 解释: 我们向 0 号工人支付 70,向 2 号工人支付 35。
示例 2:
输入: quality = [3,1,10,10,1], wage = [4,8,2,2,7], K = 3 输出: 30.66667 解释: 我们向 0 号工人支付 4,向 2 号和 3 号分别支付 13.33333。
提示:
1 <= K <= N <= 10000
,其中N = quality.length = wage.length
1 <= quality[i] <= 10000
1 <= wage[i] <= 10000
- 与正确答案误差在
10^-5
之内的答案将被视为正确的。
260ms
1 class Solution { 2 func mincostToHireWorkers(_ quality: [Int], _ wage: [Int], _ K: Int) -> Double { 3 var workers: [(wage: Int, quality: Int)] = [] 4 5 for i in 0..<quality.count { 6 workers.append((wage[i], quality[i])) 7 } 8 // Sort all workers with their expected ratio 9 workers.sort { Double($0.wage) / Double($0.quality) < Double($1.wage) / Double($1.quality) } // O(n*logn) 10 11 var heap = Heap(sort: >) 12 13 var totalWage = Double(Int.max) 14 var totalQuality = 0 15 16 for worker in workers { 17 let currRatio = Double(worker.wage)/Double(worker.quality) 18 //print(currRatio) 19 heap.push(worker.quality) 20 totalQuality += worker.quality 21 //print("total quality:", totalQuality) 22 if heap.count > K { 23 totalQuality -= heap.remove()! 24 } 25 if heap.count == K { 26 totalWage = min(totalWage, Double(totalQuality) * currRatio) 27 //print("current total wage:", totalWage) 28 } 29 } 30 31 return totalWage 32 } 33 } 34 35 // Implementation of heap 36 public struct Heap { 37 38 var elements: [Int] = [] 39 let sort: (Int, Int) -> Bool 40 var isEmpty: Bool { 41 return self.elements.isEmpty 42 } 43 44 var count: Int { 45 return self.elements.count 46 } 47 48 func peek() -> Int? { 49 return elements.first 50 } 51 52 init(sort: @escaping (Int, Int) -> Bool, elements: [Int] = []) { 53 self.sort = sort 54 self.elements = elements 55 56 if !elements.isEmpty { 57 for i in stride(from: elements.count/2 - 1, through: 0, by: -1) { 58 siftDown(from: i) 59 } 60 } 61 } 62 63 mutating func siftDown(from index: Int) { 64 var parent = index 65 while true { 66 let left = leftIndex(of: parent) 67 let right = rightIndex(of: parent) 68 var candidate = parent 69 if left < count && sort(elements[left], elements[candidate]) { 70 candidate = left 71 } 72 if right < count && sort(elements[right], elements[candidate]) { 73 candidate = right 74 } 75 if candidate == parent { 76 return 77 } 78 elements.swapAt(parent, candidate) 79 parent = candidate 80 } 81 } 82 83 mutating func siftUp(from index: Int) { 84 var child = index 85 var parent = parentIndex(of: child) 86 while child > 0 && sort(elements[child], elements[parent]) { 87 elements.swapAt(child, parent) 88 child = parent 89 parent = parentIndex(of: child) 90 } 91 } 92 93 mutating func push(_ element: Int) { 94 elements.append(element) 95 siftUp(from: count-1) 96 } 97 98 mutating func remove() -> Int? { 99 guard !isEmpty else { return nil } 100 elements.swapAt(0, count-1) 101 defer { 102 siftDown(from: 0) 103 } 104 return elements.popLast() 105 } 106 107 func leftIndex(of index: Int) -> Int { 108 return (2 * index) + 1 109 } 110 111 func rightIndex(of index: Int) -> Int { 112 return (2 * index) + 2 113 } 114 115 func parentIndex(of index: Int) -> Int { 116 return (index - 1) / 2 117 } 118 }
276ms
1 class Solution { 2 func mincostToHireWorkers(_ quality: [Int], _ wage: [Int], _ K: Int) -> Double { 3 var quaRatios = [(Int, Double)]() 4 for i in 0..<quality.count { 5 quaRatios.append((quality[i], Double(wage[i]) / Double(quality[i]))) 6 } 7 quaRatios.sort { $0.1 < $1.1 } 8 var pq = PriorityQueue<Int> { $0 > $1 } 9 var sum = 0 10 var result = Double(Int.max) 11 for (qua, ratio) in quaRatios { 12 sum += qua 13 pq.enqueue(qua) 14 if pq.count > K { 15 sum -= pq.dequeue()! 16 } 17 if pq.count == K { 18 result = min(result, ratio * Double(sum)) 19 } 20 } 21 return result 22 } 23 } 24 25 public struct PriorityQueue<T> { 26 fileprivate var heap: Heap<T> 27 28 /* 29 To create a max-priority queue, supply a > sort function. For a min-priority 30 queue, use <. 31 */ 32 public init(sort: @escaping (T, T) -> Bool) { 33 heap = Heap(sort: sort) 34 } 35 36 public var isEmpty: Bool { 37 return heap.isEmpty 38 } 39 40 public var count: Int { 41 return heap.count 42 } 43 44 public func peek() -> T? { 45 return heap.peek() 46 } 47 48 public mutating func enqueue(_ element: T) { 49 heap.insert(element) 50 } 51 52 public mutating func dequeue() -> T? { 53 return heap.remove() 54 } 55 56 /* 57 Allows you to change the priority of an element. In a max-priority queue, 58 the new priority should be larger than the old one; in a min-priority queue 59 it should be smaller. 60 */ 61 public mutating func changePriority(index i: Int, value: T) { 62 return heap.replace(index: i, value: value) 63 } 64 } 65 66 extension PriorityQueue where T: Equatable { 67 public func index(of element: T) -> Int? { 68 return heap.index(of: element) 69 } 70 } 71 72 // 73 // Heap.swift 74 // Written for the Swift Algorithm Club by Kevin Randrup and Matthijs Hollemans 75 // 76 public struct Heap<T> { 77 78 /** The array that stores the heap's nodes. */ 79 var nodes = [T]() 80 81 /** 82 * Determines how to compare two nodes in the heap. 83 * Use '>' for a max-heap or '<' for a min-heap, 84 * or provide a comparing method if the heap is made 85 * of custom elements, for example tuples. 86 */ 87 private var orderCriteria: (T, T) -> Bool 88 89 /** 90 * Creates an empty heap. 91 * The sort function determines whether this is a min-heap or max-heap. 92 * For comparable data types, > makes a max-heap, < makes a min-heap. 93 */ 94 public init(sort: @escaping (T, T) -> Bool) { 95 self.orderCriteria = sort 96 } 97 98 /** 99 * Creates a heap from an array. The order of the array does not matter; 100 * the elements are inserted into the heap in the order determined by the 101 * sort function. For comparable data types, '>' makes a max-heap, 102 * '<' makes a min-heap. 103 */ 104 public init(array: [T], sort: @escaping (T, T) -> Bool) { 105 self.orderCriteria = sort 106 configureHeap(from: array) 107 } 108 109 /** 110 * Configures the max-heap or min-heap from an array, in a bottom-up manner. 111 * Performance: This runs pretty much in O(n). 112 */ 113 private mutating func configureHeap(from array: [T]) { 114 nodes = array 115 for i in stride(from: (nodes.count/2-1), through: 0, by: -1) { 116 shiftDown(i) 117 } 118 } 119 120 public var isEmpty: Bool { 121 return nodes.isEmpty 122 } 123 124 public var count: Int { 125 return nodes.count 126 } 127 128 /** 129 * Returns the index of the parent of the element at index i. 130 * The element at index 0 is the root of the tree and has no parent. 131 */ 132 @inline(__always) internal func parentIndex(ofIndex i: Int) -> Int { 133 return (i - 1) / 2 134 } 135 136 /** 137 * Returns the index of the left child of the element at index i. 138 * Note that this index can be greater than the heap size, in which case 139 * there is no left child. 140 */ 141 @inline(__always) internal func leftChildIndex(ofIndex i: Int) -> Int { 142 return 2*i + 1 143 } 144 145 /** 146 * Returns the index of the right child of the element at index i. 147 * Note that this index can be greater than the heap size, in which case 148 * there is no right child. 149 */ 150 @inline(__always) internal func rightChildIndex(ofIndex i: Int) -> Int { 151 return 2*i + 2 152 } 153 154 /** 155 * Returns the maximum value in the heap (for a max-heap) or the minimum 156 * value (for a min-heap). 157 */ 158 public func peek() -> T? { 159 return nodes.first 160 } 161 162 /** 163 * Adds a new value to the heap. This reorders the heap so that the max-heap 164 * or min-heap property still holds. Performance: O(log n). 165 */ 166 public mutating func insert(_ value: T) { 167 nodes.append(value) 168 shiftUp(nodes.count - 1) 169 } 170 171 /** 172 * Adds a sequence of values to the heap. This reorders the heap so that 173 * the max-heap or min-heap property still holds. Performance: O(log n). 174 */ 175 public mutating func insert<S: Sequence>(_ sequence: S) where S.Iterator.Element == T { 176 for value in sequence { 177 insert(value) 178 } 179 } 180 181 /** 182 * Allows you to change an element. This reorders the heap so that 183 * the max-heap or min-heap property still holds. 184 */ 185 public mutating func replace(index i: Int, value: T) { 186 guard i < nodes.count else { return } 187 188 remove(at: i) 189 insert(value) 190 } 191 192 /** 193 * Removes the root node from the heap. For a max-heap, this is the maximum 194 * value; for a min-heap it is the minimum value. Performance: O(log n). 195 */ 196 @discardableResult public mutating func remove() -> T? { 197 guard !nodes.isEmpty else { return nil } 198 199 if nodes.count == 1 { 200 return nodes.removeLast() 201 } else { 202 // Use the last node to replace the first one, then fix the heap by 203 // shifting this new first node into its proper position. 204 let value = nodes[0] 205 nodes[0] = nodes.removeLast() 206 shiftDown(0) 207 return value 208 } 209 } 210 211 /** 212 * Removes an arbitrary node from the heap. Performance: O(log n). 213 * Note that you need to know the node's index. 214 */ 215 @discardableResult public mutating func remove(at index: Int) -> T? { 216 guard index < nodes.count else { return nil } 217 218 let size = nodes.count - 1 219 if index != size { 220 nodes.swapAt(index, size) 221 shiftDown(from: index, until: size) 222 shiftUp(index) 223 } 224 return nodes.removeLast() 225 } 226 227 /** 228 * Takes a child node and looks at its parents; if a parent is not larger 229 * (max-heap) or not smaller (min-heap) than the child, we exchange them. 230 */ 231 internal mutating func shiftUp(_ index: Int) { 232 var childIndex = index 233 let child = nodes[childIndex] 234 var parentIndex = self.parentIndex(ofIndex: childIndex) 235 236 while childIndex > 0 && orderCriteria(child, nodes[parentIndex]) { 237 nodes[childIndex] = nodes[parentIndex] 238 childIndex = parentIndex 239 parentIndex = self.parentIndex(ofIndex: childIndex) 240 } 241 242 nodes[childIndex] = child 243 } 244 245 /** 246 * Looks at a parent node and makes sure it is still larger (max-heap) or 247 * smaller (min-heap) than its childeren. 248 */ 249 internal mutating func shiftDown(from index: Int, until endIndex: Int) { 250 let leftChildIndex = self.leftChildIndex(ofIndex: index) 251 let rightChildIndex = leftChildIndex + 1 252 253 // Figure out which comes first if we order them by the sort function: 254 // the parent, the left child, or the right child. If the parent comes 255 // first, we're done. If not, that element is out-of-place and we make 256 // it "float down" the tree until the heap property is restored. 257 var first = index 258 if leftChildIndex < endIndex && orderCriteria(nodes[leftChildIndex], nodes[first]) { 259 first = leftChildIndex 260 } 261 if rightChildIndex < endIndex && orderCriteria(nodes[rightChildIndex], nodes[first]) { 262 first = rightChildIndex 263 } 264 if first == index { return } 265 266 nodes.swapAt(index, first) 267 shiftDown(from: first, until: endIndex) 268 } 269 270 internal mutating func shiftDown(_ index: Int) { 271 shiftDown(from: index, until: nodes.count) 272 } 273 274 } 275 276 // MARK: - Searching 277 extension Heap where T: Equatable { 278 279 /** Get the index of a node in the heap. Performance: O(n). */ 280 public func index(of node: T) -> Int? { 281 return nodes.index(where: { $0 == node }) 282 } 283 284 /** Removes the first occurrence of a node from the heap. Performance: O(n log n). */ 285 @discardableResult public mutating func remove(node: T) -> T? { 286 if let index = index(of: node) { 287 return remove(at: index) 288 } 289 return nil 290 } 291 }
1 class Solution { 2 func mincostToHireWorkers(_ quality: [Int], _ wage: [Int], _ K: Int) -> Double { 3 var workers:[[Double]] = [[Double]]() 4 for i in 0..<quality.count 5 { 6 workers.append([Double(wage[i]) / Double(quality[i]), Double(quality[i])]) 7 } 8 workers.sort(by:{(a:[Double],b:[Double]) -> Bool in 9 if a[0] == b[0] 10 { 11 return a[1] <= b[1] 12 } 13 else 14 { 15 return a[0] < b[0] 16 }}) 17 var res:Double = DBL_MAX 18 var qsum:Double = 0 19 var pq: PriorityQueue<Int> = PriorityQueue<Int>(false,[Int]()) 20 for worker in workers 21 { 22 let num:Double = worker[1] 23 qsum += num 24 pq.push(Int(num)) 25 if pq.count > K 26 { 27 qsum -= Double(pq.pop()!) 28 } 29 if pq.count == K 30 { 31 res = min(res, qsum * worker[0]) 32 } 33 } 34 return res 35 } 36 } 37 38 public struct PriorityQueue<T: Comparable> { 39 fileprivate var heap = [T]() 40 private let ordered: (T, T) -> Bool 41 42 //创建具有给定顺序的新PriorityQueue。 43 //order:true:降序 | false:升序 44 //StartingValues:用于初始化PriorityQueue的元素数组。 45 public init(_ ascending: Bool = false,_ startingValues: [T] = []) { 46 self.init(order: ascending ? { $0 > $1 } : { $0 < $1 }, startingValues: startingValues) 47 } 48 49 public init(order: @escaping (T, T) -> Bool, startingValues: [T] = []) { 50 ordered = order 51 //堆构造 52 heap = startingValues 53 var i = heap.count/2 - 1 54 while i >= 0 { 55 sink(i) 56 i -= 1 57 } 58 } 59 60 //优先级队列存储了多少个元素 61 public var count: Int { return heap.count } 62 63 //如果且仅当优先级队列为空时为true 64 public var isEmpty: Bool { return heap.isEmpty } 65 66 // 在优先级队列中添加新元素,复杂度:O(lg n) 67 // element: 要插入优先级队列的元素. 68 public mutating func push(_ element: T) { 69 heap.append(element) 70 swim(heap.count - 1) 71 } 72 73 //移除并返回具有最高优先级的元素(如果升序,则为最低优先级)。复杂度: O(lg n) 74 //returns:优先级队列中优先级最高的元素,如果优先级队列为空,则为零。 75 public mutating func pop() -> T? { 76 if heap.isEmpty { return nil } 77 //增加了Swift 2兼容性 78 if heap.count == 1 { return heap.removeFirst() } 79 //以便不使用同一位置的两个实例调用swap() 80 heap.swapAt(0, heap.count - 1) 81 let temp = heap.removeLast() 82 sink(0) 83 return temp 84 } 85 86 private mutating func sink(_ index: Int) { 87 var index = index 88 while 2 * index + 1 < heap.count { 89 var j = 2 * index + 1 90 if j < (heap.count - 1) && ordered(heap[j], heap[j + 1]) { j += 1 } 91 if !ordered(heap[index], heap[j]) { break } 92 heap.swapAt(index, j) 93 index = j 94 } 95 } 96 97 private mutating func swim(_ index: Int) { 98 var index = index 99 while index > 0 && ordered(heap[(index - 1) / 2], heap[index]) { 100 heap.swapAt((index - 1) / 2, index) 101 index = (index - 1) / 2 102 } 103 } 104 }
332ms
1 class Solution { 2 func mincostToHireWorkers(_ quality: [Int], _ wage: [Int], _ K: Int) -> Double { 3 var workers = [(Int, Double)]() 4 for i in 0..<quality.count { 5 workers.append((quality[i], Double(wage[i]) / Double(quality[i]))) 6 } 7 workers = workers.sorted { 8 $0.1 < $1.1 9 } 10 11 var heap = Heap<Int>(elements: [], priorityFunction: >) 12 var total = 0, res = Double.infinity 13 for (quality, ratio) in workers { 14 if heap.count == K { 15 if let top = heap.dequeue() { 16 total -= top 17 } 18 } 19 20 heap.enqueue(quality) 21 total += quality 22 if heap.count == K { 23 res = min(res, Double(total) * ratio) 24 } 25 } 26 27 return res 28 } 29 } 30 31 struct Heap<Element> 32 { 33 var elements : [Element] 34 let priorityFunction : (Element, Element) -> Bool 35 36 init(elements: [Element] = [], priorityFunction: @escaping (Element, Element) -> Bool) { 37 self.elements = elements 38 self.priorityFunction = priorityFunction 39 buildHeap() 40 } 41 42 mutating func buildHeap() { 43 for index in (0 ..< count / 2).reversed() { 44 siftDown(elementAtIndex: index) 45 } 46 } 47 48 var isEmpty : Bool { return elements.isEmpty } 49 var count : Int { return elements.count } 50 51 func peek() -> Element? { 52 return elements.first 53 } 54 55 mutating func enqueue(_ element: Element) { 56 elements.append(element) 57 siftUp(elementAtIndex: count - 1) 58 } 59 60 mutating func siftUp(elementAtIndex index: Int) { 61 let parent = parentIndex(of: index) 62 guard !isRoot(index), 63 isHigherPriority(at: index, than: parent) 64 else { return } 65 swapElement(at: index, with: parent) 66 siftUp(elementAtIndex: parent) 67 } 68 69 mutating func dequeue() -> Element? { 70 guard !isEmpty 71 else { return nil } 72 swapElement(at: 0, with: count - 1) 73 let element = elements.removeLast() 74 if !isEmpty { 75 siftDown(elementAtIndex: 0) 76 } 77 return element 78 } 79 80 mutating func siftDown(elementAtIndex index: Int) { 81 let childIndex = highestPriorityIndex(for: index) 82 if index == childIndex { 83 return 84 } 85 swapElement(at: index, with: childIndex) 86 siftDown(elementAtIndex: childIndex) 87 } 88 89 // Helper functions 90 91 func isRoot(_ index: Int) -> Bool { 92 return index == 0 93 } 94 95 func leftChildIndex(of index: Int) -> Int { 96 return (2 * index) + 1 97 } 98 99 func rightChildIndex(of index: Int) -> Int { 100 return (2 * index) + 2 101 } 102 103 func parentIndex(of index: Int) -> Int { 104 return (index - 1) / 2 105 } 106 107 func isHigherPriority(at firstIndex: Int, than secondIndex: Int) -> Bool { 108 return priorityFunction(elements[firstIndex], elements[secondIndex]) 109 } 110 111 func highestPriorityIndex(of parentIndex: Int, and childIndex: Int) -> Int { 112 guard childIndex < count && isHigherPriority(at: childIndex, than: parentIndex) 113 else { return parentIndex } 114 return childIndex 115 } 116 117 func highestPriorityIndex(for parent: Int) -> Int { 118 return highestPriorityIndex(of: highestPriorityIndex(of: parent, and: leftChildIndex(of: parent)), and: rightChildIndex(of: parent)) 119 } 120 121 mutating func swapElement(at firstIndex: Int, with secondIndex: Int) { 122 guard firstIndex != secondIndex 123 else { return } 124 elements.swapAt(firstIndex, secondIndex) 125 } 126 } 127 128 // A bonus extra for you: two extra functions, if the Element type is Equatable 129 extension Heap where Element : Equatable { 130 131 // This function allows you to remove an element from the heap, in a similar way to how you would dequeue the root element. 132 mutating func remove(_ element: Element) { 133 guard let index = elements.index(of: element) 134 else { return } 135 swapElement(at: index, with: count - 1) 136 elements.remove(at: count - 1) 137 siftDown(elementAtIndex: index) 138 } 139 140 // This function allows you to 'boost' an element, by sifting the element up the heap. You might do this if the element is already in the heap, but its priority has increased since it was enqueued. 141 mutating func boost(_ element: Element) { 142 guard let index = elements.index(of: element) 143 else { return } 144 siftUp(elementAtIndex: index) 145 } 146 }
376ms
1 class Solution { 2 class Heap { 3 var arr = [0] 4 var count: Int { 5 return arr.count-1 6 } 7 8 var top: Int { 9 return arr[1] 10 } 11 12 func insert(_ num: Int) -> Void { 13 arr.append(num) 14 var i = arr.count-1 15 while i > 1 { 16 if arr[i] > arr[i/2] { 17 (arr[i], arr[i/2]) = (arr[i/2], arr[i]) 18 } else { 19 break 20 } 21 i /= 2 22 } 23 } 24 25 func pop() -> Int { 26 var ret = self.top 27 var last = arr.removeLast() 28 if self.count == 0 { 29 return ret 30 } 31 32 arr[1] = last 33 var i = 1 34 while i < arr.count { 35 let left = i*2 36 let right = i*2+1 37 var next = i 38 if left < arr.count && arr[left] > arr[next] { 39 next = left 40 } 41 if right < arr.count && arr[right] > arr[next] { 42 next = right 43 } 44 if i != next { 45 (arr[i], arr[next]) = (arr[next], arr[i]) 46 i = next 47 } else { 48 break 49 } 50 51 } 52 return ret 53 } 54 } 55 func mincostToHireWorkers(_ quality: [Int], _ wage: [Int], _ K: Int) -> Double { 56 57 var n = quality.count 58 59 var ranks = [Int](repeating: 0, count: n) 60 var ratios = [Double](repeating: 0.0, count: n) 61 62 for i in 0..<n { 63 ranks[i] = i 64 ratios[i] = Double(wage[i])/Double(quality[i]) 65 } 66 67 ranks.sort { (i1, i2) in 68 if ratios[i1] == ratios[i2] { 69 return quality[i1] < quality[i2] 70 } else { 71 return ratios[i1] < ratios[i2] 72 } 73 } 74 75 var sum = 0.0; 76 var heap = Heap() 77 78 var ans = 1e9 79 80 for rank in ranks { 81 heap.insert(quality[rank]) 82 sum += Double(quality[rank]) 83 if heap.count > K { 84 var maxQ = heap.pop() 85 sum -= Double(maxQ) 86 } 87 if heap.count == K { 88 // print(ans, sum, ratios[rank]) 89 ans = min(ans, sum*ratios[rank]) 90 } 91 } 92 return ans 93 } 94 }