Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 1147b6b

Browse files
optimal binary search tree added in dynamic_programming (TheAlgorithms#890)
* optimal search binary tree added * obst link in DIRECTORY.md
1 parent a3b116d commit 1147b6b

File tree

3 files changed

+96
-0
lines changed

3 files changed

+96
-0
lines changed

DIRECTORY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@
9797
* [Maximal Square](https://github.com/TheAlgorithms/Rust/blob/master/src/dynamic_programming/maximal_square.rs)
9898
* [Maximum Subarray](https://github.com/TheAlgorithms/Rust/blob/master/src/dynamic_programming/maximum_subarray.rs)
9999
* [Minimum Cost Path](https://github.com/TheAlgorithms/Rust/blob/master/src/dynamic_programming/minimum_cost_path.rs)
100+
* [Optimal Binary Seacrh Tree](https://github.com/TheAlgorithms/Rust/blob/master/src/dynamic_programming/optimal_bst.rs)
100101
* [Rod Cutting](https://github.com/TheAlgorithms/Rust/blob/master/src/dynamic_programming/rod_cutting.rs)
101102
* [Snail](https://github.com/TheAlgorithms/Rust/blob/master/src/dynamic_programming/snail.rs)
102103
* [Subset Generation](https://github.com/TheAlgorithms/Rust/blob/master/src/dynamic_programming/subset_generation.rs)

src/dynamic_programming/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ mod matrix_chain_multiply;
1212
mod maximal_square;
1313
mod maximum_subarray;
1414
mod minimum_cost_path;
15+
mod optimal_bst;
1516
mod rod_cutting;
1617
mod snail;
1718
mod subset_generation;
@@ -40,6 +41,7 @@ pub use self::matrix_chain_multiply::matrix_chain_multiply;
4041
pub use self::maximal_square::maximal_square;
4142
pub use self::maximum_subarray::maximum_subarray;
4243
pub use self::minimum_cost_path::minimum_cost_path;
44+
pub use self::optimal_bst::optimal_search_tree;
4345
pub use self::rod_cutting::rod_cut;
4446
pub use self::snail::snail;
4547
pub use self::subset_generation::list_subset;
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
// Optimal Binary Search Tree Algorithm in Rust
2+
// Time Complexity: O(n^3) with prefix sum optimization
3+
// Space Complexity: O(n^2) for the dp table and prefix sum array
4+
5+
/// Constructs an Optimal Binary Search Tree from a list of key frequencies.
6+
/// The goal is to minimize the expected search cost given key access frequencies.
7+
///
8+
/// # Arguments
9+
/// * `freq` - A slice of integers representing the frequency of key access
10+
///
11+
/// # Returns
12+
/// * An integer representing the minimum cost of the optimal BST
13+
pub fn optimal_search_tree(freq: &[i32]) -> i32 {
14+
let n = freq.len();
15+
if n == 0 {
16+
return 0;
17+
}
18+
19+
// dp[i][j] stores the cost of optimal BST that can be formed from keys[i..=j]
20+
let mut dp = vec![vec![0; n]; n];
21+
22+
// prefix_sum[i] stores sum of freq[0..i]
23+
let mut prefix_sum = vec![0; n + 1];
24+
for i in 0..n {
25+
prefix_sum[i + 1] = prefix_sum[i] + freq[i];
26+
}
27+
28+
// Base case: Trees with only one key
29+
for i in 0..n {
30+
dp[i][i] = freq[i];
31+
}
32+
33+
// Build chains of increasing length l (from 2 to n)
34+
for l in 2..=n {
35+
for i in 0..=n - l {
36+
let j = i + l - 1;
37+
dp[i][j] = i32::MAX;
38+
39+
// Compute the total frequency sum in the range [i..=j] using prefix sum
40+
let fsum = prefix_sum[j + 1] - prefix_sum[i];
41+
42+
// Try making each key in freq[i..=j] the root of the tree
43+
for r in i..=j {
44+
// Cost of left subtree
45+
let left = if r > i { dp[i][r - 1] } else { 0 };
46+
// Cost of right subtree
47+
let right = if r < j { dp[r + 1][j] } else { 0 };
48+
49+
// Total cost = left + right + sum of frequencies (fsum)
50+
let cost = left + right + fsum;
51+
52+
// Choose the minimum among all possible roots
53+
if cost < dp[i][j] {
54+
dp[i][j] = cost;
55+
}
56+
}
57+
}
58+
}
59+
60+
// Minimum cost of the optimal BST storing all keys
61+
dp[0][n - 1]
62+
}
63+
64+
#[cfg(test)]
65+
mod tests {
66+
use super::*;
67+
68+
// Macro to generate multiple test cases for the optimal_search_tree function
69+
macro_rules! optimal_bst_tests {
70+
($($name:ident: $input:expr => $expected:expr,)*) => {
71+
$(
72+
#[test]
73+
fn $name() {
74+
let freq = $input;
75+
assert_eq!(optimal_search_tree(freq), $expected);
76+
}
77+
)*
78+
};
79+
}
80+
81+
optimal_bst_tests! {
82+
// Common test cases
83+
test_case_1: &[34, 10, 8, 50] => 180,
84+
test_case_2: &[10, 12] => 32,
85+
test_case_3: &[10, 12, 20] => 72,
86+
test_case_4: &[25, 10, 20] => 95,
87+
test_case_5: &[4, 2, 6, 3] => 26,
88+
89+
// Edge test cases
90+
test_case_single: &[42] => 42,
91+
test_case_empty: &[] => 0,
92+
}
93+
}

0 commit comments

Comments
 (0)