Skip to content

Commit 1338b16

Browse files
committed
feat: optimal-binary-search-tree challenge
1 parent 3dd86d8 commit 1338b16

File tree

3 files changed

+49
-0
lines changed

3 files changed

+49
-0
lines changed
2.77 KB
Binary file not shown.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Challenge: Given search frequencies for different elements, implement a dynamic programming algorithm
2+
# to construct an optimal binary search tree minimizing the average search cost.
3+
# Use object-oriented programming and follow the DRY principle.
4+
5+
from optimal_bst import OptimalBST
6+
7+
def main():
8+
keys = [10, 12, 20]
9+
freq = [34, 8, 50]
10+
optimal_bst = OptimalBST(keys, freq)
11+
cost = optimal_bst.optimal_cost()
12+
print(f"Optimal BST cost: {cost}")
13+
14+
if __name__ == "__main__":
15+
main()
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
from typing import List
2+
3+
class OptimalBST:
4+
def __init__(self, keys: List[int], freq: List[int]):
5+
self.keys = keys
6+
self.freq = freq
7+
self.n = len(keys)
8+
self.dp = [[0] * self.n for _ in range(self.n)]
9+
10+
def optimal_cost(self) -> int:
11+
# Precompute prefix sums for frequencies
12+
prefix_sum = [0] * (self.n + 1)
13+
for i in range(self.n):
14+
prefix_sum[i + 1] = prefix_sum[i] + self.freq[i]
15+
16+
def get_sum(i, j):
17+
return prefix_sum[j + 1] - prefix_sum[i]
18+
19+
def cost_for_root(i, j, r):
20+
left = self.dp[i][r - 1] if r > i else 0
21+
right = self.dp[r + 1][j] if r < j else 0
22+
return left + right + get_sum(i, j)
23+
24+
for i in range(self.n):
25+
self.dp[i][i] = self.freq[i]
26+
27+
for length in range(2, self.n + 1):
28+
for i in range(self.n - length + 1):
29+
j = i + length - 1
30+
self.dp[i][j] = min(
31+
cost_for_root(i, j, r) for r in range(i, j + 1)
32+
)
33+
34+
return self.dp[0][self.n - 1]

0 commit comments

Comments
 (0)