|
1 | 1 | # [Problem 703: Kth Largest Element in a Stream](https://leetcode.com/problems/kth-largest-element-in-a-stream/description/?envType=daily-question)
|
2 | 2 |
|
3 | 3 | ## Initial thoughts (stream-of-consciousness)
|
| 4 | +- Kind of a fun one! |
| 5 | +- Inside the class, let's keep a running (sorted) list of the $k$ largest elements |
| 6 | +- When the class is initialized, we'll need to sort `nums` in descending order and set `self.k_largest` to the $k$ largest numbers (from largest to smallest) |
| 7 | +- When a number is added: |
| 8 | + - If the number is less than or equal to the smallest number in `self.k_largest` (i.e., `self.k_largest[-1]`), return `self.k_largest[-1]` |
| 9 | + - If the number is (strictly) greater than the smallest number in `self.k_largest`: |
| 10 | + - Drop the current $k^\mathrm{th}$ largest number (`self.k_largest = self.k_largest[:-1]`) |
| 11 | + - Loop through each element in the sequence until we find a place to insert `val`: |
| 12 | + ```python |
| 13 | + inserted = False |
| 14 | + for i, x in enumerate(self.k_largest): |
| 15 | + if x <= val: |
| 16 | + self.k_largest = [*self.k_largest[:i], val, *self.k_largest[i:]] |
| 17 | + inserted = True |
| 18 | + break |
| 19 | + if not inserted: |
| 20 | + self.k_largest.append(val) |
| 21 | + return self.k_largest[-1] |
| 22 | + ``` |
4 | 23 |
|
5 | 24 | ## Refining the problem, round 2 thoughts
|
| 25 | +- One thing I'm not sure of: are we guaranteed to get at least $k$ numbers when the class is intialized? I'll account for this (by appending -1's) just in case |
| 26 | +- Nothing particularly tricky here...let's just implement the solution |
6 | 27 |
|
7 | 28 | ## Attempted solution(s)
|
8 | 29 | ```python
|
9 |
| -class Solution: # paste your code here! |
10 |
| - ... |
| 30 | +class KthLargest: |
| 31 | + def __init__(self, k: int, nums: List[int]): |
| 32 | + self.k_largest = list(sorted(nums, reverse=True))[:k] |
| 33 | + if len(self.k_largest) < k: |
| 34 | + self.k_largest.extend([-1] * (k - len(nums))) |
| 35 | + |
| 36 | + def add(self, val: int) -> int: |
| 37 | + if val <= self.k_largest[-1]: |
| 38 | + return self.k_largest[-1] |
| 39 | + self.k_largest.pop() |
| 40 | + |
| 41 | + inserted = False |
| 42 | + for i, x in enumerate(self.k_largest): |
| 43 | + if x <= val: |
| 44 | + self.k_largest = [*self.k_largest[:i], val, *self.k_largest[i:]] |
| 45 | + inserted = True |
| 46 | + break |
| 47 | + if not inserted: |
| 48 | + self.k_largest.append(val) |
| 49 | + return self.k_largest[-1] |
11 | 50 | ```
|
| 51 | +- The given test case passes |
| 52 | +- It's somewhat annoying to create new test cases, but let's see... |
| 53 | + - `["KthLargest","add","add","add","add","add"], [[5,[4,5,8,2]],[3],[5],[10],[9],[4]]`: pass |
| 54 | + - `["KthLargest","add","add","add","add","add","add","add"], [[6,[0,20,4,5,8,2]],[3],[21],[3],[5],[10],[9],[4]]`: pass |
| 55 | +- I think we're good...submitting... |
| 56 | + |
| 57 | + |
| 58 | + |
| 59 | +🤦 Ah-- I misread the instructions (I thought we couldn't have negative numbers). Easy fix... |
| 60 | + |
| 61 | +```python |
| 62 | +class KthLargest: |
| 63 | + def __init__(self, k: int, nums: List[int]): |
| 64 | + self.k_largest = list(sorted(nums, reverse=True))[:k] |
| 65 | + if len(self.k_largest) < k: |
| 66 | + self.k_largest.extend([-float("inf")] * (k - len(nums))) |
| 67 | + |
| 68 | + def add(self, val: int) -> int: |
| 69 | + if val <= self.k_largest[-1]: |
| 70 | + return self.k_largest[-1] |
| 71 | + self.k_largest.pop() |
| 72 | + |
| 73 | + inserted = False |
| 74 | + for i, x in enumerate(self.k_largest): |
| 75 | + if x <= val: |
| 76 | + self.k_largest = [*self.k_largest[:i], val, *self.k_largest[i:]] |
| 77 | + inserted = True |
| 78 | + break |
| 79 | + if not inserted: |
| 80 | + self.k_largest.append(val) |
| 81 | + return self.k_largest[-1] |
| 82 | +``` |
| 83 | + |
| 84 | + |
| 85 | + |
| 86 | +Hah! Did I win the prize for the slowest solution? In any case, I'll take it: solved 🥳! |
| 87 | + |
| 88 | +- Note: a heap is definitely the way to solve this efficiently. I could have used the built-in `heapq` (from the `heapq` module). |
| 89 | +- Let's see if I can get it to work quickly... |
| 90 | + |
| 91 | +```python |
| 92 | +import heapq |
| 93 | + |
| 94 | +class KthLargest: |
| 95 | + def __init__(self, k: int, nums: List[int]): |
| 96 | + self.k = k |
| 97 | + self.k_largest = nums |
| 98 | + heapq.heapify(self.k_largest) |
| 99 | + while len(self.k_largest) > self.k: |
| 100 | + heapq.heappop(self.k_largest) |
| 101 | + |
| 102 | + def add(self, val: int) -> int: |
| 103 | + heapq.heappush(self.k_largest, val) |
| 104 | + while len(self.k_largest) > self.k: |
| 105 | + heapq.heappop(self.k_largest) |
| 106 | + return self.k_largest[0] |
| 107 | +``` |
| 108 | +- That took a some hacking around based on the [heapq documentation](https://docs.python.org/3/library/heapq.html) but I got it to run... |
| 109 | +- Given test cases pass; submitting... |
| 110 | + |
| 111 | + |
| 112 | + |
| 113 | +There we go-- quite a lot faster! |
| 114 | + |
| 115 | + |
0 commit comments