Skip to content

Commit a6f1652

Browse files
committed
daily: Lca of deepest leaves, RUST update
Add daily solution, try to use cargo to manage all rust solutions, rust has better unit test than c++, definitely.
1 parent fb0f94e commit a6f1652

File tree

4 files changed

+198
-6
lines changed

4 files changed

+198
-6
lines changed

daily/25-Apr4.cc

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#include <algorithm>
2+
#include <functional>
3+
using namespace std;
4+
5+
struct TreeNode {
6+
int val;
7+
TreeNode* left;
8+
TreeNode* right;
9+
TreeNode() : val(0), left(nullptr), right(nullptr) {}
10+
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
11+
TreeNode(int x, TreeNode* left, TreeNode* right) : val(x), left(left), right(right) {}
12+
};
13+
14+
class Solution {
15+
public:
16+
TreeNode* lcaDeepestLeaves(TreeNode* root) {
17+
TreeNode* ans = nullptr;
18+
int max_depth = -1; // max depth
19+
20+
using DfsFunction = function<int(TreeNode*, int)>;
21+
22+
function<int(TreeNode*, int)> dfs = [&](TreeNode* node, int depth) {
23+
if (node == nullptr) {
24+
max_depth = max(max_depth, depth);
25+
return depth;
26+
}
27+
28+
int left_max_depth = dfs(node->left, depth + 1);
29+
int right_max_depth = dfs(node->right, depth + 1);
30+
if (left_max_depth == right_max_depth && left_max_depth == max_depth) {
31+
ans = node;
32+
}
33+
return max(left_max_depth, right_max_depth);
34+
};
35+
36+
// auto dfs = [&](auto&& dfs, TreeNode* node, int depth) {
37+
// if (node == nullptr) {
38+
// max_depth = max(max_depth, depth);
39+
// return depth;
40+
// }
41+
42+
// int left_max_depth = dfs(node->left, depth + 1);
43+
// int right_max_depth = dfs(node->right, depth + 1);
44+
// if (left_max_depth == right_max_depth && left_max_depth == max_depth) {
45+
// ans = node;
46+
// }
47+
// return max(left_max_depth, right_max_depth);
48+
// };
49+
dfs(root, 0);
50+
return ans;
51+
}
52+
};

rust/Cargo.toml

+5-1
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,8 @@ edition = "2021"
1010

1111
[lib]
1212
doctest = false
13-
test = true
13+
test = true
14+
15+
[[bin]]
16+
name = "lca_deepest_leaves"
17+
path = "src/tree/25-Apr4.rs"

rust/src/tree/25-Apr4.rs

+136
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
use std::{cell::RefCell, rc::Rc};
2+
use rust::util::tree::TreeNode;
3+
4+
// Define Solution struct
5+
pub struct Solution {}
6+
7+
impl Solution {
8+
pub fn lca_deepest_leaves(root: Option<Rc<RefCell<TreeNode>>>) -> Option<Rc<RefCell<TreeNode>>> {
9+
let mut ans = None;
10+
let mut max_depth = -1; // max global depth
11+
12+
fn dfs(node: &Option<Rc<RefCell<TreeNode>>>, depth: i32, max_depth: &mut i32, ans: &mut Option<Rc<RefCell<TreeNode>>>) -> i32 {
13+
if let Some(node) = node {
14+
let x = node.borrow();
15+
let left_max_depth = dfs(&x.left, depth + 1, max_depth, ans); // left sub tree
16+
let right_max_depth = dfs(&x.right, depth + 1, max_depth, ans); // right sub tree
17+
if left_max_depth == right_max_depth && left_max_depth == *max_depth {
18+
*ans = Some(node.clone());
19+
}
20+
left_max_depth.max(right_max_depth)
21+
} else {
22+
*max_depth = (*max_depth).max(depth); // global max depth
23+
depth
24+
}
25+
}
26+
27+
dfs(&root, 0, &mut max_depth, &mut ans);
28+
ans
29+
}
30+
}
31+
32+
// Add a main function to avoid the "main function not found" error
33+
fn main() {
34+
// Example usage can be added here
35+
println!("LCA of Deepest Leaves implementation");
36+
}
37+
38+
#[cfg(test)]
39+
mod tests {
40+
use super::*;
41+
use rust::util::tree::{to_tree, TreeNode};
42+
43+
#[test]
44+
fn test_lca_deepest_leaves_example1() {
45+
// Create a tree: [3,5,1,6,2,0,8,null,null,7,4]
46+
// 3
47+
// / \
48+
// 5 1
49+
// / \ / \
50+
// 6 2 0 8
51+
// / \
52+
// 7 4
53+
let root = Some(Rc::new(RefCell::new(TreeNode::new(3))));
54+
let node5 = Rc::new(RefCell::new(TreeNode::new(5)));
55+
let node1 = Rc::new(RefCell::new(TreeNode::new(1)));
56+
let node6 = Rc::new(RefCell::new(TreeNode::new(6)));
57+
let node2 = Rc::new(RefCell::new(TreeNode::new(2)));
58+
let node0 = Rc::new(RefCell::new(TreeNode::new(0)));
59+
let node8 = Rc::new(RefCell::new(TreeNode::new(8)));
60+
let node7 = Rc::new(RefCell::new(TreeNode::new(7)));
61+
let node4 = Rc::new(RefCell::new(TreeNode::new(4)));
62+
63+
// Link the nodes
64+
node2.borrow_mut().left = Some(node7.clone());
65+
node2.borrow_mut().right = Some(node4.clone());
66+
67+
node5.borrow_mut().left = Some(node6.clone());
68+
node5.borrow_mut().right = Some(node2.clone());
69+
70+
node1.borrow_mut().left = Some(node0.clone());
71+
node1.borrow_mut().right = Some(node8.clone());
72+
73+
root.as_ref().unwrap().borrow_mut().left = Some(node5.clone());
74+
root.as_ref().unwrap().borrow_mut().right = Some(node1.clone());
75+
76+
// Expected output: node 2, as it's the lowest common ancestor of the deepest nodes (7 and 4)
77+
let result = Solution::lca_deepest_leaves(root);
78+
assert!(result.is_some());
79+
assert_eq!(result.unwrap().borrow().val, 2);
80+
}
81+
82+
#[test]
83+
fn test_lca_deepest_leaves_example2() {
84+
// Create a tree: [1]
85+
let root = Some(Rc::new(RefCell::new(TreeNode::new(1))));
86+
87+
// Expected output: node 1, as it's the only node
88+
let result = Solution::lca_deepest_leaves(root);
89+
assert!(result.is_some());
90+
assert_eq!(result.unwrap().borrow().val, 1);
91+
}
92+
93+
#[test]
94+
fn test_lca_deepest_leaves_example3() {
95+
// Create a tree: [1,2,3,4,5]
96+
// 1
97+
// / \
98+
// 2 3
99+
// / \
100+
// 4 5
101+
102+
// Using the utility function to_tree for easier tree creation
103+
let vec = vec![Some(1), Some(2), Some(3), Some(4), Some(5)];
104+
let root = to_tree(vec);
105+
106+
// Expected output: node 2, as it's the lowest common ancestor of the deepest nodes (4 and 5)
107+
let result = Solution::lca_deepest_leaves(root);
108+
assert!(result.is_some());
109+
assert_eq!(result.unwrap().borrow().val, 2);
110+
}
111+
112+
#[test]
113+
fn test_lca_deepest_leaves_unbalanced() {
114+
// Create an unbalanced tree: [1,2,null,3,null,4]
115+
// 1
116+
// /
117+
// 2
118+
// /
119+
// 3
120+
// /
121+
// 4
122+
let root = Some(Rc::new(RefCell::new(TreeNode::new(1))));
123+
let node2 = Rc::new(RefCell::new(TreeNode::new(2)));
124+
let node3 = Rc::new(RefCell::new(TreeNode::new(3)));
125+
let node4 = Rc::new(RefCell::new(TreeNode::new(4)));
126+
127+
node3.borrow_mut().left = Some(node4.clone());
128+
node2.borrow_mut().left = Some(node3.clone());
129+
root.as_ref().unwrap().borrow_mut().left = Some(node2.clone());
130+
131+
// Expected output: node 4, as it's the deepest node
132+
let result = Solution::lca_deepest_leaves(root);
133+
assert!(result.is_some());
134+
assert_eq!(result.unwrap().borrow().val, 4);
135+
}
136+
}

rust/src/util/tree.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
use std::{cell::RefCell, rc::Rc};
22

33
#[derive(PartialEq, Eq, Debug)]
4-
struct TreeNode {
5-
val: i32,
6-
left: Option<Rc<RefCell<TreeNode>>>,
7-
right: Option<Rc<RefCell<TreeNode>>>,
4+
pub struct TreeNode {
5+
pub val: i32,
6+
pub left: Option<Rc<RefCell<TreeNode>>>,
7+
pub right: Option<Rc<RefCell<TreeNode>>>,
88
}
99

1010
impl TreeNode {
@@ -53,4 +53,4 @@ macro_rules! tree {
5353
}
5454
};
5555
($($e:expr,)*) => {(tree![$($e),*])}
56-
}
56+
}

0 commit comments

Comments
 (0)