Skip to content

Commit 67fdea4

Browse files
committed
More solutions, bonus problems folder
1 parent a3f1573 commit 67fdea4

File tree

6 files changed

+213
-0
lines changed

6 files changed

+213
-0
lines changed

bonus/max_perf_tree.py

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
from utils.graphs import BiNode, ltbt
2+
3+
4+
def maximum_perfect_tree(tree_root: BiNode):
5+
max_now = 0
6+
7+
def max_perf_tree_depth(root: BiNode) -> int:
8+
nonlocal max_now
9+
if not root:
10+
return 0
11+
12+
l_max = max_perf_tree_depth(root.left)
13+
r_max = max_perf_tree_depth(root.right)
14+
val_now = 1 + min(l_max, r_max)
15+
16+
if val_now > max_now:
17+
max_now = val_now
18+
19+
return val_now
20+
21+
max_perf_tree_depth(tree_root)
22+
return 2**max_now -1
23+
24+
25+
if __name__ == "__main__":
26+
tree_arr = [1] +\
27+
[2, 3] + \
28+
[None, 4] + [5, 6] +\
29+
[None, None] + [None, None] + [7, 8] + [9, 10]
30+
[None] * 14 + [11]
31+
example_root = ltbt(tree_arr)
32+
print(f"Max tree is {maximum_perfect_tree(example_root)}")

bonus/spiral_copy.py

Whitespace-only changes.

chapter_10/p10_3.py

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
def search_rot_arr(arr_rotated, num):
2+
n = len(arr_rotated)
3+
4+
if not arr_rotated:
5+
return -1
6+
elif n == 1:
7+
return 0 if arr_rotated[0] == num else -1
8+
elif arr_rotated[0] < arr_rotated[-1]:
9+
return binary_search(arr_rotated, 0, n-1, num)
10+
11+
pivot_index = find_pivot_index(arr_rotated)
12+
res_index = -1
13+
14+
print(f"Found pivot index: {pivot_index}")
15+
16+
search_start, search_end = \
17+
(pivot_index+1, n-1) if num <= arr_rotated[-1] else (0, pivot_index)
18+
return binary_search(arr_rotated, search_start, search_end, num)
19+
20+
21+
def binary_search(arr, s, e, target):
22+
low = s
23+
high = e
24+
while low <= high:
25+
mid = (low + high) // 2
26+
27+
if arr[mid] == target:
28+
return mid
29+
elif arr[mid] > target:
30+
high = mid-1
31+
else:
32+
low = mid+1
33+
34+
return -1
35+
36+
37+
def find_pivot_index(arr):
38+
"""Addresable index of the last element before pivot"""
39+
low = 0
40+
high = len(arr)-1
41+
42+
while low <= high:
43+
mid = (low+high) // 2 # Divide and floor
44+
45+
if mid == len(arr):
46+
return 0
47+
48+
if arr[mid+1] < arr[mid]:
49+
return mid
50+
51+
if arr[mid] > arr[-1]:
52+
low = mid+1
53+
else:
54+
high = mid - 1
55+
56+
return 0
57+
58+
59+
if __name__ == "__main__":
60+
exs = [([2], 2),
61+
([1, 2], 2),
62+
([0, 1, 2, 3, 4, 5], 1),
63+
([9, 12, 17, 2, 4, 5], 17),
64+
([9, 12, 17, 2, 4, 5, 6], 4)]
65+
for arr, target in exs:
66+
print(
67+
f"Looking for {target} in {arr}, found location ? {search_rot_arr(arr, target)}")

chapter_10/p10_4.py

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
class Listy:
2+
def __init__(self, arr):
3+
self.arr = arr
4+
5+
def elemAt(self, index: int):
6+
return self.arr[index] if index < len(self.arr) else -1
7+
8+
def search_unsized_list(arr: Listy, target: int) -> int:
9+
# Lenght is not known
10+
ind = 0
11+
low = 0
12+
while arr.elemAt(ind) != -1 and arr.elemAt(ind) <= target:
13+
ce = arr.elemAt(ind)
14+
low = ind
15+
if not ind:
16+
ind = 1
17+
else:
18+
ind *= 2
19+
20+
high = ind
21+
while low <= high:
22+
# print(f"Looking at low and high {low} and {high}")
23+
mid = (low + high) // 2
24+
ce = arr.elemAt(mid)
25+
if ce == target:
26+
return mid
27+
elif ce == -1 or ce > target:
28+
high = mid - 1
29+
else:
30+
low = mid + 1
31+
return -1
32+
33+
34+
if __name__ == "__main__":
35+
exs = [([1, 2, 3, 4, 5, 6, 7, 8], 10),
36+
([12, 13, 14, 15], 15),
37+
(list(range(62)), 61)]
38+
for arr, target in exs:
39+
listy_arr = Listy(arr)
40+
print(
41+
f"Looking for {target} in {arr}, found location ?"
42+
f" {search_unsized_list(listy_arr, target)}")

chapter_10/p10_5.py

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
from typing import List
2+
3+
4+
def sparse_search(warr: List[str], target):
5+
low = 0
6+
high = len(warr) - 1
7+
while low <= high:
8+
mid = (low + high) // 2
9+
10+
# Go right until limit or non-empty
11+
while mid < high and not warr[mid]:
12+
mid += 1
13+
14+
if warr[mid] == target:
15+
return mid
16+
elif (not warr[mid]) or warr[mid] > target:
17+
# In case that right side is empty, look left
18+
high = mid-1
19+
else:
20+
low = mid+1
21+
return -1
22+
23+
24+
if __name__ == "__main__":
25+
test_arr = ['b', '', '', 'car', '', '', 'tar', '', '', '', '', 'zar']
26+
exs = [(test_arr, 'zar'),
27+
(test_arr, 'car'),
28+
(test_arr, "potato"),
29+
(test_arr, 'b'),
30+
([''], "potato"),
31+
(['', 'aaa', ''], 'aaa'),
32+
(['aaa'], 'aaa')]
33+
for arr, target in exs:
34+
print(f"Position of {target}\tis {sparse_search(arr,target)}\tin {arr}")

chapter_17/p17_20.py

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import heapq as hq
2+
3+
4+
class MedianHolder:
5+
6+
def __init__(self):
7+
self.left_heap = [] # Max (on top) heap
8+
self.right_heap = [] # Min (on top) heap
9+
self.size = 0
10+
11+
def add_elem(self, x: int):
12+
13+
if self.left_heap and x > -self.left_heap[0]:
14+
hq.heappush(self.right_heap, x)
15+
else:
16+
hq.heappush(self.left_heap, -x)
17+
18+
if len(self.left_heap) < len(self.right_heap): # Too much on right
19+
hq.heappush(self.left_heap, - hq.heappop(self.right_heap))
20+
elif len(self.left_heap) > len(self.right_heap) + 1: # Too much on left
21+
hq.heappush(self.right_heap, -hq.heappop(self.left_heap))
22+
23+
self.size += 1
24+
25+
def get_median(self):
26+
if self.size == 0:
27+
raise Exception("No elems")
28+
if self.size % 2 == 0:
29+
return (-self.left_heap[0] + self.right_heap[0]) / 2
30+
else:
31+
return -self.left_heap[0]
32+
33+
34+
if __name__ == "__main__":
35+
mh = MedianHolder()
36+
for i in range(25):
37+
mh.add_elem(i)
38+
print(f"At elem {i}\t, Median is now {mh.get_median()} ")

0 commit comments

Comments
 (0)