Skip to content

Commit 19bfc55

Browse files
committed
AlgoExpert Min Heap Construction
1 parent a2f4d8c commit 19bfc55

File tree

2 files changed

+137
-0
lines changed

2 files changed

+137
-0
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1045,6 +1045,7 @@ First column links to the problem in AlgoExpert, second is the problem's difficu
10451045
| [Kadane's Algorithm][ae&kadane's-algorithm] | 🟠 Medium | [![python](res/py.png)][ae&kadane's-algorithm#py] |
10461046
| [Knapsack Problem][ae&knapsack-problem] | 🔴 Hard | [![python](res/py.png)][ae&knapsack-problem#py] |
10471047
| [Merge Sort][ae&merge-sort] | 🟣 Very Hard | [![python](res/py.png)][ae&merge-sort#py] |
1048+
| [Min Heap Construction][ae&min-heap-construction] | 🟠 Medium | [![python](res/py.png)][ae&min-heap-construction#py] |
10481049
| [Remove Duplicates From Linked List][ae&remove-duplicates-from-linked-list] | 🟢 Easy | [![python](res/py.png)][ae&remove-duplicates-from-linked-list#py] |
10491050
| [Remove Islands][ae&remove-islands] | 🟠 Medium | [![python](res/py.png)][ae&remove-islands#py] |
10501051
| [Validate BST][ae&validate-bst] | 🟠 Medium | [![python](res/py.png)][ae&validate-bst#py] |
@@ -1067,6 +1068,8 @@ First column links to the problem in AlgoExpert, second is the problem's difficu
10671068
[ae&knapsack-problem#py]: algoexpert/knapsack-problem.py
10681069
[ae&merge-sort]: https://www.algoexpert.io/questions/merge-sort
10691070
[ae&merge-sort#py]: algoexpert/merge-sort.py
1071+
[ae&min-heap-construction]: https://www.algoexpert.io/questions/min-heap-construction
1072+
[ae&min-heap-construction#py]: algoexpert/min-heap-construction.py
10701073
[ae&remove-islands]: https://www.algoexpert.io/questions/remove-islands
10711074
[ae&remove-islands#py]: algoexpert/remove-islands.py
10721075
[ae&remove-duplicates-from-linked-list]: https://www.algoexpert.io/questions/remove-duplicates-from-linked-list

algoexpert/min-heap-construction.py

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
# Min Heap Construction
2+
# 🟠 Medium
3+
#
4+
# https://www.algoexpert.io/questions/min-heap-construction
5+
#
6+
# Tags: Heap (Priority Queue)
7+
8+
import timeit
9+
from typing import List
10+
11+
12+
# Do not edit the class below except for the buildHeap,
13+
# siftDown, siftUp, peek, remove, and insert methods.
14+
# Feel free to add new properties and methods to the class.
15+
class MinHeapRecursive:
16+
def __init__(self, array):
17+
# Do not edit the line below.
18+
self.heap = self.buildHeap(array)
19+
20+
# Heapify assumes that the leaves are correct heaps and starts
21+
# building heaps from the first non-leaf node in reverse to the
22+
# root node.
23+
# Time complexity: O(n)
24+
# Space O(log(n)) - The call could potentially reach the height of
25+
# the binary heap.
26+
def buildHeap(self, array):
27+
for i in range(len(array) // 2 - 1, -1, -1):
28+
self.siftDown(array, i)
29+
return array
30+
31+
# Time complexity: O(log(n))
32+
# Space O(log(n)) - recursive call
33+
def siftDown(self, arr: List[int], i: int):
34+
smallest, l, r = i, 2 * i + 1, 2 * i + 2
35+
# If left child is smaller than root.
36+
if l < len(arr) and arr[l] < arr[smallest]:
37+
smallest = l
38+
# If right child is smaller than smallest so far.
39+
if r < len(arr) and arr[r] < arr[smallest]:
40+
smallest = r
41+
# If largest is not root, swap their position.
42+
if smallest != i:
43+
arr[i], arr[smallest] = arr[smallest], arr[i]
44+
# Recursively heapify the affected left or right sub-tree.
45+
self.siftDown(arr, smallest)
46+
47+
# Time complexity: O(log(n))
48+
# Space O(log(n)) - recursive call
49+
def siftUp(self, arr: List[int], i: int):
50+
parent_idx = (i - 1) >> 1
51+
if arr[parent_idx] > arr[i]:
52+
arr[i], arr[parent_idx] = arr[parent_idx], arr[i]
53+
self.siftUp(arr, parent_idx)
54+
return arr
55+
56+
# Time complexity: O(1)
57+
# Space O(1)
58+
def peek(self):
59+
return self.heap[0]
60+
61+
# Time complexity: O(log(n))
62+
# Space O(log(n))
63+
def remove(self):
64+
val = self.heap[0]
65+
self.heap[0] = self.heap.pop()
66+
self.siftDown(self.heap, 0)
67+
return val
68+
69+
# Time complexity: O(log(n))
70+
# Space O(log(n))
71+
def insert(self, value):
72+
self.heap.append(value)
73+
self.heap = self.siftUp(self.heap, len(self.heap) - 1)
74+
75+
76+
def test():
77+
executors = [
78+
MinHeapRecursive,
79+
]
80+
tests = [
81+
[
82+
[
83+
"MinHeap",
84+
"insert",
85+
"peek",
86+
"remove",
87+
"peek",
88+
"remove",
89+
"peek",
90+
"insert",
91+
"remove",
92+
"remove",
93+
"remove",
94+
"peek",
95+
],
96+
[
97+
[48, 12, 24, 7, 8, -5, 24, 391, 24, 56, 2, 6, 8, 41],
98+
[76],
99+
[],
100+
[],
101+
[],
102+
[],
103+
[],
104+
[83],
105+
],
106+
[None, None, -5, -5, 2, 2, 6, None, 6, 7, 8, 8],
107+
],
108+
]
109+
for executor in executors:
110+
start = timeit.default_timer()
111+
for _ in range(1):
112+
for col, t in enumerate(tests):
113+
sol = executor(t[1][0])
114+
for i in range(1, len(t[0])):
115+
call = t[0][i]
116+
if call == "insert":
117+
argument = t[1][i][0]
118+
result = getattr(sol, call)(argument)
119+
else:
120+
result = getattr(sol, call)()
121+
exp = t[2][i]
122+
assert result == exp, (
123+
f"\033[93m» {result} <> {exp}\033[91m for"
124+
+ f" test {col}.{i} {call}({argument}) using "
125+
+ f"\033[1m{executor.__name__}"
126+
)
127+
stop = timeit.default_timer()
128+
used = str(round(stop - start, 5))
129+
cols = "{0:20}{1:10}{2:10}"
130+
res = cols.format(executor.__name__, used, "seconds")
131+
print(f"\033[92m» {res}\033[0m")
132+
133+
134+
test()

0 commit comments

Comments
 (0)