diff --git a/java/1985-Find-The-Kth-Largest-Integer-In-The-Array.java b/java/1985-Find-The-Kth-Largest-Integer-In-The-Array.java new file mode 100644 index 000000000..a32c8f80e --- /dev/null +++ b/java/1985-Find-The-Kth-Largest-Integer-In-The-Array.java @@ -0,0 +1,32 @@ +// Min Heap comparator for reverse priority queue +class StringNumberComparartor implements Comparator { + @Override + public int compare(String s1, String s2) { + if(s1.length() != s2.length()) { + return (s1.length() - s2.length()); + } + int len = s1.length(); + for(int i=0; i pq = new PriorityQueue<>(new StringNumberComparartor()); + + for(String numStr: nums) { + pq.add(numStr); + if(pq.size() > k) { + pq.remove(); + } + } + + return pq.peek(); + } +} \ No newline at end of file diff --git a/swift/1985-Find-The-Kth-Largest-Integer-In-The-Array.swift b/swift/1985-Find-The-Kth-Largest-Integer-In-The-Array.swift new file mode 100644 index 000000000..24ad345d1 --- /dev/null +++ b/swift/1985-Find-The-Kth-Largest-Integer-In-The-Array.swift @@ -0,0 +1,143 @@ +class Solution { + func kthLargestNumber(_ nums: [String], _ k: Int) -> String { + // Use a Min Heap for storing upto k-elements max in the priority queue + var heap: Heap = Heap(sort: { (str1, str2) in + guard str1.count == str2.count else { return str1.count < str2.count } + for (c1, c2) in zip(str1, str2) { + guard c1 == c2 else { return c1 < c2 } + } + return false + }) + + nums.forEach { num in + heap.insert(num) + if heap.count > k { + heap.remove() + } + } + + return heap.peek() ?? "" + } +} + +// Heap used from https://github.com/kodecocodes/swift-algorithm-club/blob/master/Heap/Heap.swift +public struct Heap { + var nodes = [T]() + + private var orderCriteria: (T, T) -> Bool + + public init(sort: @escaping (T, T) -> Bool) { + self.orderCriteria = sort + } + + public init(array: [T], sort: @escaping (T, T) -> Bool) { + self.orderCriteria = sort + configureHeap(from: array) + } + + private mutating func configureHeap(from array: [T]) { + nodes = array + for i in stride(from: (nodes.count/2-1), through: 0, by: -1) { + shiftDown(i) + } + } + + public var isEmpty: Bool { + return nodes.isEmpty + } + + public var count: Int { + return nodes.count + } + + @inline(__always) internal func parentIndex(ofIndex i: Int) -> Int { + return (i - 1) / 2 + } + + @inline(__always) internal func leftChildIndex(ofIndex i: Int) -> Int { + return 2*i + 1 + } + + @inline(__always) internal func rightChildIndex(ofIndex i: Int) -> Int { + return 2*i + 2 + } + + public func peek() -> T? { + return nodes.first + } + + public mutating func insert(_ value: T) { + nodes.append(value) + shiftUp(nodes.count - 1) + } + + public mutating func insert(_ sequence: S) where S.Iterator.Element == T { + for value in sequence { + insert(value) + } + } + + public mutating func replace(index i: Int, value: T) { + guard i < nodes.count else { return } + remove(at: i) + insert(value) + } + + @discardableResult public mutating func remove() -> T? { + guard !nodes.isEmpty else { return nil } + if nodes.count == 1 { + return nodes.removeLast() + } else { + let value = nodes[0] + nodes[0] = nodes.removeLast() + shiftDown(0) + return value + } + } + + @discardableResult public mutating func remove(at index: Int) -> T? { + guard index < nodes.count else { return nil } + let size = nodes.count - 1 + if index != size { + nodes.swapAt(index, size) + shiftDown(from: index, until: size) + shiftUp(index) + } + return nodes.removeLast() + } + + internal mutating func shiftUp(_ index: Int) { + var childIndex = index + let child = nodes[childIndex] + var parentIndex = self.parentIndex(ofIndex: childIndex) + + while childIndex > 0 && orderCriteria(child, nodes[parentIndex]) { + nodes[childIndex] = nodes[parentIndex] + childIndex = parentIndex + parentIndex = self.parentIndex(ofIndex: childIndex) + } + + nodes[childIndex] = child + } + + internal mutating func shiftDown(from index: Int, until endIndex: Int) { + let leftChildIndex = self.leftChildIndex(ofIndex: index) + let rightChildIndex = leftChildIndex + 1 + + var first = index + if leftChildIndex < endIndex && orderCriteria(nodes[leftChildIndex], nodes[first]) { + first = leftChildIndex + } + if rightChildIndex < endIndex && orderCriteria(nodes[rightChildIndex], nodes[first]) { + first = rightChildIndex + } + if first == index { return } + + nodes.swapAt(index, first) + shiftDown(from: first, until: endIndex) + } + + internal mutating func shiftDown(_ index: Int) { + shiftDown(from: index, until: nodes.count) + } +} \ No newline at end of file