Kth Largest Number in a Stream (medium)
Resources for finding the largest number in a stream.
Dry-run templates
This is the implementation of the solution provided for the problem posed in the lesson:
from heapq import *class KthLargestNumberInStream:minHeap = []def __init__(self, nums, k):self.k = k# add the numbers in the min heapfor num in nums:self.add(num)def add(self, num):# add the new number in the min heapheappush(self.minHeap, num)# if heap has more than 'k' numbers, remove one numberif len(self.minHeap) > self.k:heappop(self.minHeap)# return the 'Kth largest numberreturn self.minHeap[0]def main():kthLargestNumber = KthLargestNumberInStream([3, 1, 5, 12, 2, 11], 4)print("4th largest number is: " + str(kthLargestNumber.add(6)))print("4th largest number is: " + str(kthLargestNumber.add(13)))print("4th largest number is: " + str(kthLargestNumber.add(4)))main()
Students may be encouraged to run through the provided solution with the following sample inputs.
Sample input #1
Input: [3, 1, 5, 12, 2, 11], K = 4
Line number | num | minHeap | Kth largest element (minHeap[0]) |
27 | - | [] | - |
10 - 11, 15 | 3 | [3] | 3 |
10 - 11, 15 | 1 | [1, 3] | 1 |
10 - 11, 15 | 5 | [1, 3, 5] | 1 |
10 - 11, 15 | 12 | [1, 3, 5, 12] | 1 |
10 - 11, 15 | 2 | [1, 2, 5, 12, 3] | 1 |
18 - 19 | 2 | [2, 3, 5, 12] | 2 |
10 - 11, 15 | 11 | [2, 3, 5, 12, 11] | 2 |
18 - 19 | 11 | [3, 11, 5, 12] | 3 |
Sample input #2
Input: [3, 1, 5, 12, 2, 11, 6], K = 4
Line number | num | minHeap | Kth largest element (minHeap[0]) |
27 | - | [] | - |
10 - 11, 15 | 3 | [3] | 3 |
10 - 11, 15 | 1 | [1, 3] | 1 |
10 - 11, 15 | 5 | [1, 3, 5] | 1 |
10 - 11, 15 | 12 | [1, 3, 5, 12] | 1 |
10 - 11, 15 | 2 | [1, 2, 5, 12, 3] | 1 |
18 - 19 | 2 | [2, 3, 5, 12] | 2 |
10 - 11, 15 | 11 | [2, 3, 5, 12, 11] | 2 |
18 - 19 | 11 | [3, 11, 5, 12] | 3 |
10 - 11, 15 | 6 | [3, 6, 5, 12, 11] | 3 |
18 - 19 | 6 | [5, 6, 11, 12] | 5 |
Step-by-step solution construction
We’ll be using a heap to find the k
th largest element in a given stream of numbers.
The first step is to populate our heap. We’ll iterate over the stream values and push them on to the heap using the class’s add()
function.
We can either initialize a stream of numbers directly and the constructor in our class will call the add()
function itself, or we can populate using the add()
function manually. For example, consider a stream of numbers . We can populate our heap in either of the following manner:
# Constructor method
kthLargestNumber = KthLargestNumberInStream([1,2,3,4,5], k)
# Manually calling the 'add' function
kthLargestNumber = KthLargestNumberInStream([], k)
KthLargestNumberInStream.add(1)
KthLargestNumberInStream.add(2)
KthLargestNumberInStream.add(3)
KthLargestNumberInStream.add(4)
KthLargestNumberInStream.add(5)
We can also use both methods together. We have added a utility function, result()
to our class, that returns the smallest element in the heap. Let’s see this below:
from heapq import *class KthLargestNumberInStream:minHeap = []def __init__(self, nums, k):self.k = k# add the numbers in the min heapfor num in nums:self.add(num)def add(self, num):# add the new number in the min heapprint("Pushing",num, "on to the heap.")heappush(self.minHeap, num)print("Heap: ", self.minHeap, "\n")def result(self):# return the smallest number in the heapreturn self.minHeap[0]def main():kthLargestNumber = KthLargestNumberInStream([3, 1, 5, 12, 2, 11], 4)print("Smallest number in the heap is: " + str(kthLargestNumber.result()))print("-"*100 + "\n")input = [6, 13, -1, 4]for i in input:kthLargestNumber.add(i)print("Smallest number in the heap is: " + str(kthLargestNumber.result()))print("-"*100 + "\n")main()
Since we want the k
th largest element, we’ll add a condition to only keep k
elements in our heap. When the size of our heap exceeds k
, we pop one number. In that state, after the pop operation, our k
th largest element will be at the top of the heap, that is, the first element.
from heapq import *class KthLargestNumberInStream:minHeap = []def __init__(self, nums, k):self.k = k# add the numbers in the min heapfor num in nums:self.add(num)def add(self, num):# add the new number in the min heapprint("Pushing",num, "on to the heap.")heappush(self.minHeap, num)print("\tHeap: ", self.minHeap)# if heap has more than 'k' numbers, remove one numberif len(self.minHeap) > self.k:print("\tSize of heap: " + str(len(self.minHeap)) + ". Since it's greater than our k = " + str(self.k) + ", we pop from the heap.")heappop(self.minHeap)print("\tHeap after the pop operation: " + str(self.minHeap))print("")def result(self):# return the smallest number in the heapreturn self.minHeap[0]def main():kthLargestNumber = KthLargestNumberInStream([3, 1, 5, 12, 2, 11], 4)print("4th largest number in the heap is: " + str(kthLargestNumber.result()))print("-"*100 + "\n")input = [6, 13, -1, 4]for i in input:kthLargestNumber.add(i)print("4th largest number in the heap is: " + str(kthLargestNumber.result()))print("-"*100 + "\n")main()
Lastly, we return the top element of our heap since it’s our k
th largest element. The return statement executes every time we add a new element to the heap until we’ve reached the end of our stream.
from heapq import *class KthLargestNumberInStream:minHeap = []def __init__(self, nums, k):self.k = k# add the numbers in the min heapfor num in nums:self.add(num)def add(self, num):# add the new number in the min heapprint("Pushing",num, "on to the heap.")heappush(self.minHeap, num)print("\tHeap: ", self.minHeap)# if heap has more than 'k' numbers, remove one numberif len(self.minHeap) > self.k:print("\tSize of heap: " + str(len(self.minHeap)) + ". Since it's greater than our k = " + str(self.k) + ", we pop.")heappop(self.minHeap)print("\tHeap after the pop operation: " + str(self.minHeap))# return the 'Kth largest numberprint("\tReturning the first element of the heap: " + str(self.minHeap[0]) + "\n")return self.minHeap[0]def result(self):# return the smallest number in the heapreturn self.minHeap[0]def main():kthLargestNumber = KthLargestNumberInStream([3, 1, 5, 12, 2, 11], 4)print("4th largest number is: " + str(kthLargestNumber.result()))print("-"*100 + "\n")input = [6, 13, -1, 4]for i in input:print("4th largest number is: " + str(kthLargestNumber.add(i)))print("-"*100 + "\n")main()