|
| 1 | +class Solution { |
| 2 | + func getOrder(_ tasks: [[Int]]) -> [Int] { |
| 3 | + guard tasks.count > 1 else { |
| 4 | + return [0] |
| 5 | + } |
| 6 | + |
| 7 | + var tasksSorted = [(Int, Int, Int)]() // (StartTime, ProcessingTime, OriginalTaskIndex) |
| 8 | + for (index, item) in tasks.enumerated() { |
| 9 | + tasksSorted.append((item[0], item[1], index)) |
| 10 | + } |
| 11 | + tasksSorted = tasksSorted.sorted(by: { $0.0 == $1.0 ? ($0.1 == $1.1 ? $0.2 < $1.2 : $0.1 < $1.1) : $0.0 < $1.0 }) |
| 12 | + |
| 13 | + var result = [Int]() |
| 14 | + var minHeap = Heap<(Int, Int, Int)>(sort: { |
| 15 | + $0.1 == $1.1 ? $0.2 < $1.2 : $0.1 < $1.1 |
| 16 | + }) |
| 17 | + var (currentSortedTaskIndex, currentTime) = (0, tasksSorted.first!.0) |
| 18 | + while result.count < tasksSorted.count { |
| 19 | + while currentSortedTaskIndex < tasksSorted.count && tasksSorted[currentSortedTaskIndex].0 <= currentTime { |
| 20 | + minHeap.insert(tasksSorted[currentSortedTaskIndex]) |
| 21 | + currentSortedTaskIndex += 1 |
| 22 | + } |
| 23 | + |
| 24 | + if !minHeap.isEmpty { |
| 25 | + let (_, processingTime, index) = minHeap.remove()! |
| 26 | + result.append(index) |
| 27 | + currentTime += processingTime |
| 28 | + } else if currentSortedTaskIndex < tasksSorted.count { |
| 29 | + currentTime = tasksSorted[currentSortedTaskIndex].0 |
| 30 | + } |
| 31 | + } |
| 32 | + return result |
| 33 | + } |
| 34 | +} |
| 35 | + |
| 36 | + |
| 37 | +//SOURCE: https://github.com/raywenderlich/swift-algorithm-club/blob/master/Heap/Heap.swift |
| 38 | +// |
| 39 | +// Heap.swift |
| 40 | +// Written for the Swift Algorithm Club by Kevin Randrup and Matthijs Hollemans |
| 41 | +// |
| 42 | +public struct Heap<T> { |
| 43 | + |
| 44 | + /** The array that stores the heap's nodes. */ |
| 45 | + var nodes = [T]() |
| 46 | + |
| 47 | + /** |
| 48 | + * Determines how to compare two nodes in the heap. |
| 49 | + * Use '>' for a max-heap or '<' for a min-heap, |
| 50 | + * or provide a comparing method if the heap is made |
| 51 | + * of custom elements, for example tuples. |
| 52 | + */ |
| 53 | + private var orderCriteria: (T, T) -> Bool |
| 54 | + |
| 55 | + /** |
| 56 | + * Creates an empty heap. |
| 57 | + * The sort function determines whether this is a min-heap or max-heap. |
| 58 | + * For comparable data types, > makes a max-heap, < makes a min-heap. |
| 59 | + */ |
| 60 | + public init(sort: @escaping (T, T) -> Bool) { |
| 61 | + self.orderCriteria = sort |
| 62 | + } |
| 63 | + |
| 64 | + /** |
| 65 | + * Creates a heap from an array. The order of the array does not matter; |
| 66 | + * the elements are inserted into the heap in the order determined by the |
| 67 | + * sort function. For comparable data types, '>' makes a max-heap, |
| 68 | + * '<' makes a min-heap. |
| 69 | + */ |
| 70 | + public init(array: [T], sort: @escaping (T, T) -> Bool) { |
| 71 | + self.orderCriteria = sort |
| 72 | + configureHeap(from: array) |
| 73 | + } |
| 74 | + |
| 75 | + /** |
| 76 | + * Configures the max-heap or min-heap from an array, in a bottom-up manner. |
| 77 | + * Performance: This runs pretty much in O(n). |
| 78 | + */ |
| 79 | + private mutating func configureHeap(from array: [T]) { |
| 80 | + nodes = array |
| 81 | + for i in stride(from: (nodes.count/2-1), through: 0, by: -1) { |
| 82 | + shiftDown(i) |
| 83 | + } |
| 84 | + } |
| 85 | + |
| 86 | + public var isEmpty: Bool { |
| 87 | + return nodes.isEmpty |
| 88 | + } |
| 89 | + |
| 90 | + public var count: Int { |
| 91 | + return nodes.count |
| 92 | + } |
| 93 | + |
| 94 | + /** |
| 95 | + * Returns the index of the parent of the element at index i. |
| 96 | + * The element at index 0 is the root of the tree and has no parent. |
| 97 | + */ |
| 98 | + @inline(__always) internal func parentIndex(ofIndex i: Int) -> Int { |
| 99 | + return (i - 1) / 2 |
| 100 | + } |
| 101 | + |
| 102 | + /** |
| 103 | + * Returns the index of the left child of the element at index i. |
| 104 | + * Note that this index can be greater than the heap size, in which case |
| 105 | + * there is no left child. |
| 106 | + */ |
| 107 | + @inline(__always) internal func leftChildIndex(ofIndex i: Int) -> Int { |
| 108 | + return 2*i + 1 |
| 109 | + } |
| 110 | + |
| 111 | + /** |
| 112 | + * Returns the index of the right child of the element at index i. |
| 113 | + * Note that this index can be greater than the heap size, in which case |
| 114 | + * there is no right child. |
| 115 | + */ |
| 116 | + @inline(__always) internal func rightChildIndex(ofIndex i: Int) -> Int { |
| 117 | + return 2*i + 2 |
| 118 | + } |
| 119 | + |
| 120 | + /** |
| 121 | + * Returns the maximum value in the heap (for a max-heap) or the minimum |
| 122 | + * value (for a min-heap). |
| 123 | + */ |
| 124 | + public func peek() -> T? { |
| 125 | + return nodes.first |
| 126 | + } |
| 127 | + |
| 128 | + /** |
| 129 | + * Adds a new value to the heap. This reorders the heap so that the max-heap |
| 130 | + * or min-heap property still holds. Performance: O(log n). |
| 131 | + */ |
| 132 | + public mutating func insert(_ value: T) { |
| 133 | + nodes.append(value) |
| 134 | + shiftUp(nodes.count - 1) |
| 135 | + } |
| 136 | + |
| 137 | + /** |
| 138 | + * Adds a sequence of values to the heap. This reorders the heap so that |
| 139 | + * the max-heap or min-heap property still holds. Performance: O(log n). |
| 140 | + */ |
| 141 | + public mutating func insert<S: Sequence>(_ sequence: S) where S.Iterator.Element == T { |
| 142 | + for value in sequence { |
| 143 | + insert(value) |
| 144 | + } |
| 145 | + } |
| 146 | + |
| 147 | + /** |
| 148 | + * Allows you to change an element. This reorders the heap so that |
| 149 | + * the max-heap or min-heap property still holds. |
| 150 | + */ |
| 151 | + public mutating func replace(index i: Int, value: T) { |
| 152 | + guard i < nodes.count else { return } |
| 153 | + |
| 154 | + remove(at: i) |
| 155 | + insert(value) |
| 156 | + } |
| 157 | + |
| 158 | + /** |
| 159 | + * Removes the root node from the heap. For a max-heap, this is the maximum |
| 160 | + * value; for a min-heap it is the minimum value. Performance: O(log n). |
| 161 | + */ |
| 162 | + @discardableResult public mutating func remove() -> T? { |
| 163 | + guard !nodes.isEmpty else { return nil } |
| 164 | + |
| 165 | + if nodes.count == 1 { |
| 166 | + return nodes.removeLast() |
| 167 | + } else { |
| 168 | + // Use the last node to replace the first one, then fix the heap by |
| 169 | + // shifting this new first node into its proper position. |
| 170 | + let value = nodes[0] |
| 171 | + nodes[0] = nodes.removeLast() |
| 172 | + shiftDown(0) |
| 173 | + return value |
| 174 | + } |
| 175 | + } |
| 176 | + |
| 177 | + /** |
| 178 | + * Removes an arbitrary node from the heap. Performance: O(log n). |
| 179 | + * Note that you need to know the node's index. |
| 180 | + */ |
| 181 | + @discardableResult public mutating func remove(at index: Int) -> T? { |
| 182 | + guard index < nodes.count else { return nil } |
| 183 | + |
| 184 | + let size = nodes.count - 1 |
| 185 | + if index != size { |
| 186 | + nodes.swapAt(index, size) |
| 187 | + shiftDown(from: index, until: size) |
| 188 | + shiftUp(index) |
| 189 | + } |
| 190 | + return nodes.removeLast() |
| 191 | + } |
| 192 | + |
| 193 | + /** |
| 194 | + * Takes a child node and looks at its parents; if a parent is not larger |
| 195 | + * (max-heap) or not smaller (min-heap) than the child, we exchange them. |
| 196 | + */ |
| 197 | + internal mutating func shiftUp(_ index: Int) { |
| 198 | + var childIndex = index |
| 199 | + let child = nodes[childIndex] |
| 200 | + var parentIndex = self.parentIndex(ofIndex: childIndex) |
| 201 | + |
| 202 | + while childIndex > 0 && orderCriteria(child, nodes[parentIndex]) { |
| 203 | + nodes[childIndex] = nodes[parentIndex] |
| 204 | + childIndex = parentIndex |
| 205 | + parentIndex = self.parentIndex(ofIndex: childIndex) |
| 206 | + } |
| 207 | + |
| 208 | + nodes[childIndex] = child |
| 209 | + } |
| 210 | + |
| 211 | + /** |
| 212 | + * Looks at a parent node and makes sure it is still larger (max-heap) or |
| 213 | + * smaller (min-heap) than its childeren. |
| 214 | + */ |
| 215 | + internal mutating func shiftDown(from index: Int, until endIndex: Int) { |
| 216 | + let leftChildIndex = self.leftChildIndex(ofIndex: index) |
| 217 | + let rightChildIndex = leftChildIndex + 1 |
| 218 | + |
| 219 | + // Figure out which comes first if we order them by the sort function: |
| 220 | + // the parent, the left child, or the right child. If the parent comes |
| 221 | + // first, we're done. If not, that element is out-of-place and we make |
| 222 | + // it "float down" the tree until the heap property is restored. |
| 223 | + var first = index |
| 224 | + if leftChildIndex < endIndex && orderCriteria(nodes[leftChildIndex], nodes[first]) { |
| 225 | + first = leftChildIndex |
| 226 | + } |
| 227 | + if rightChildIndex < endIndex && orderCriteria(nodes[rightChildIndex], nodes[first]) { |
| 228 | + first = rightChildIndex |
| 229 | + } |
| 230 | + if first == index { return } |
| 231 | + |
| 232 | + nodes.swapAt(index, first) |
| 233 | + shiftDown(from: first, until: endIndex) |
| 234 | + } |
| 235 | + |
| 236 | + internal mutating func shiftDown(_ index: Int) { |
| 237 | + shiftDown(from: index, until: nodes.count) |
| 238 | + } |
| 239 | + |
| 240 | +} |
| 241 | + |
| 242 | +// MARK: - Searching |
| 243 | +extension Heap where T: Equatable { |
| 244 | + |
| 245 | + /** Get the index of a node in the heap. Performance: O(n). */ |
| 246 | + public func index(of node: T) -> Int? { |
| 247 | + return nodes.index(where: { $0 == node }) |
| 248 | + } |
| 249 | + |
| 250 | + /** Removes the first occurrence of a node from the heap. Performance: O(n). */ |
| 251 | + @discardableResult public mutating func remove(node: T) -> T? { |
| 252 | + if let index = index(of: node) { |
| 253 | + return remove(at: index) |
| 254 | + } |
| 255 | + return nil |
| 256 | + } |
| 257 | + |
| 258 | +} |
0 commit comments