Skip to content

Commit 608e7b1

Browse files
committed
feat(algorithms, heaps): top k and kth largest
1 parent 6cb240c commit 608e7b1

21 files changed

+227
-0
lines changed
File renamed without changes.
File renamed without changes.
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# Top-K Largest Elements in an Array
2+
3+
Given an integer array nums, return the 3 largest elements in the array in any order.
4+
5+
## Example
6+
7+
```text
8+
Input: nums = [9, 3, 7, 1, -2, 6, 8]
9+
Output: [8, 7, 9]
10+
# or [7, 9, 8] or [9, 7, 8] ...
11+
```
12+
13+
## Solution
14+
15+
Here's how we can solve this problem using a min-heap:
16+
17+
- Create a min-heap that stores the first 3 elements of the array. These represent the 3 largest elements we have seen so
18+
far, with the smallest of the 3 at the root of the heap.
19+
![Solution 1](./images/solutions/top_k_largest_element_in_array_solution_1.png)
20+
21+
- Iterate through the remaining elements in the array.
22+
- If the current element is larger than the root of the heap, pop the root and push the current element into the heap.
23+
- Otherwise, continue to the next element.
24+
25+
![Solution 2](./images/solutions/top_k_largest_element_in_array_solution_2.png)
26+
![Solution 3](./images/solutions/top_k_largest_element_in_array_solution_3.png)
27+
![Solution 4](./images/solutions/top_k_largest_element_in_array_solution_4.png)
28+
![Solution 5](./images/solutions/top_k_largest_element_in_array_solution_5.png)
29+
30+
After iterating through all the elements, the heap contains the 3 largest elements in the array.
31+
32+
### Complexity Analysis
33+
34+
#### Time Complexity Breakdown
35+
36+
- The heapify function takes O(3) = O(1) time
37+
- We iterate through all elements in the array once: O(n) time
38+
- The heappop and heappush operations take O(log 3) = O(1) time each
39+
40+
#### Space Complexity
41+
42+
- We use a heap of size 3 to store the 3 largest elements: O(3) = O(1) space
43+
- The algorithm uses constant space regardless of input size
44+
45+
Note: The time and space complexity become more interesting when 3 is a variable number k.
46+
47+
---
48+
49+
# Kth Largest Element in an Array
50+
51+
Write a function that takes an array of unsorted integers nums and an integer k, and returns the kth largest element in
52+
the array. This function should run in O(n log k) time, where n is the length of the array.
53+
54+
## Examples
55+
56+
```text
57+
Input:
58+
nums = [5, 3, 2, 1, 4]
59+
k = 2
60+
61+
Output: 4
62+
```
63+
64+
## Solutions
65+
66+
- [Approach 1](#approach-1-sorting)
67+
- [Approach 2](#approach-2-min-heap)
68+
69+
### Approach 1: Sorting
70+
71+
The simplest approach is to sort the array in descending order and return the kth element. This approach has a time
72+
complexity of O(n log n) where n is the number of elements in the array, and a space complexity of O(1).
73+
74+
### Approach 2: Min Heap
75+
76+
By using a min-heap, we can reduce the time complexity to O(n log k), where n is the number of elements in the array and
77+
k is the value of k.
78+
The idea behind this solution is to iterate over the elements in the array while storing the k largest elements we've
79+
seen so far in a min-heap. At each element, we check if it is greater than the smallest element (the root) of the heap.
80+
If it is, we pop the smallest element from the heap and push the current element into the heap. This way, the heap will
81+
always contain the k largest elements we've seen so far.
82+
After iterating over all the elements, the root of the heap will be the kth largest element in the array.
83+
84+
![Solution 2.1](./images/solutions/kth_largest_element_in_array_solution_1.png)
85+
![Solution 2.2](./images/solutions/kth_largest_element_in_array_solution_2.png)
86+
![Solution 2.3](./images/solutions/kth_largest_element_in_array_solution_3.png)
87+
![Solution 2.4](./images/solutions/kth_largest_element_in_array_solution_4.png)
88+
![Solution 2.5](./images/solutions/kth_largest_element_in_array_solution_5.png)
89+
![Solution 2.6](./images/solutions/kth_largest_element_in_array_solution_6.png)
90+
![Solution 2.7](./images/solutions/kth_largest_element_in_array_solution_7.png)
91+
![Solution 2.8](./images/solutions/kth_largest_element_in_array_solution_8.png)
92+
![Solution 2.9](./images/solutions/kth_largest_element_in_array_solution_9.png)
93+
![Solution 2.10](./images/solutions/kth_largest_element_in_array_solution_10.png)
94+
![Solution 2.11](./images/solutions/kth_largest_element_in_array_solution_11.png)
95+
96+
#### Complexity Analysis
97+
98+
##### Time Complexity: O(n log k)
99+
100+
Where n is the number of elements in the array and k is the input parameter. We iterate over
101+
all elements, and in the worst case, we both push and pop each element from the heap, which takes O(log k) time per
102+
element.
103+
104+
##### Space Complexity: O(k)
105+
106+
Where k is the input parameter. The space is used by the heap to store the k largest elements.
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
from typing import List
2+
import heapq
3+
4+
5+
def k_largest(nums: List[int], k: int = 3) -> List[int]:
6+
"""
7+
Finds the k largest elements in a given list. K is defaulted to three, but can be used to tweak the k largest
8+
elements in the array
9+
Args:
10+
nums(list): list of elements to check for
11+
k(int): number of elements to check, defaulted to 3
12+
Returns:
13+
list: top k largest elements
14+
"""
15+
# create a minimum heap with the first k elements
16+
min_heap = nums[:k]
17+
heapq.heapify(min_heap)
18+
19+
# iterate through the remaining elements
20+
for num in nums[k:]:
21+
# if the current number is greater than the element at the top of the heap
22+
if num > min_heap[0]:
23+
# Remove it and add this element
24+
heapq.heappushpop(min_heap, num)
25+
26+
# return the top k elements
27+
return min_heap
28+
29+
30+
def kth_largest(nums: List[int], k: int) -> int:
31+
"""
32+
Finds the kth largest element in a given list
33+
Args:
34+
nums(list): list of elements to check for
35+
k(int): the kth largest element to return
36+
Returns:
37+
int: the kth largest element
38+
"""
39+
# input validation to ensure we don't get unexpected results
40+
if not nums or k <= 0 or k > len(nums):
41+
return -1
42+
43+
# create a minimum heap with the first k elements
44+
min_heap = []
45+
46+
# iterate through the remaining elements
47+
for num in nums:
48+
if len(min_heap) < k:
49+
heapq.heappush(min_heap, num)
50+
# if the current number is greater than the element at the top of the heap
51+
elif num > min_heap[0]:
52+
# Remove it and add this element
53+
heapq.heappushpop(min_heap, num)
54+
55+
# return the top kth element
56+
return min_heap[0]
57+
58+
59+
def kth_largest_sorting(nums: List[int], k: int) -> int:
60+
"""
61+
Finds the kth largest element in a given list using sorting
62+
Args:
63+
nums(list): list of elements to check for
64+
k(int): the kth largest element to return
65+
Returns:
66+
int: the kth largest element
67+
"""
68+
# input validation to ensure we don't get unexpected results
69+
if not nums or k <= 0 or k > len(nums):
70+
return -1
71+
72+
# Sort the list in place which incurs a time complexity cost of O(n log(n)). Space complexity is O(n) due to using
73+
# an in-memory data structure to store the elements during sorting using timsort in Python
74+
nums.sort(reverse=True)
75+
# Return the kth largest element
76+
return nums[k - 1]
31.7 KB
Loading
48.7 KB
Loading
30.8 KB
Loading
28.1 KB
Loading
26.8 KB
Loading
40.2 KB
Loading

0 commit comments

Comments
 (0)