forked from neetcode-gh/leetcode
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
1985. Find the Kth Largest Integer in the Array
- Loading branch information
Showing
2 changed files
with
175 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
// Min Heap comparator for reverse priority queue | ||
class StringNumberComparartor implements Comparator<String> { | ||
@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<len; i++) { | ||
char c1 = s1.charAt(i), c2 = s2.charAt(i); | ||
if(c1 == c2) { continue; } | ||
return (c1 - c2); | ||
} | ||
return 0; | ||
} | ||
} | ||
|
||
class Solution { | ||
public String kthLargestNumber(String[] nums, int k) { | ||
// Reverse pq to store only k elements [i.e. Min Heap] | ||
PriorityQueue<String> pq = new PriorityQueue<>(new StringNumberComparartor()); | ||
|
||
for(String numStr: nums) { | ||
pq.add(numStr); | ||
if(pq.size() > k) { | ||
pq.remove(); | ||
} | ||
} | ||
|
||
return pq.peek(); | ||
} | ||
} |
143 changes: 143 additions & 0 deletions
143
swift/1985-Find-The-Kth-Largest-Integer-In-The-Array.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<String> = 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<T> { | ||
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<S: Sequence>(_ 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) | ||
} | ||
} |