Skip to content

Commit

Permalink
Add problem 1932: Merge BSTs to Create Single BST
Browse files Browse the repository at this point in the history
  • Loading branch information
EFanZh committed Jul 28, 2024
1 parent b2fc03d commit d502b21
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1435,6 +1435,7 @@ pub mod problem_1926_nearest_exit_from_entrance_in_maze;
pub mod problem_1927_sum_game;
pub mod problem_1929_concatenation_of_array;
pub mod problem_1930_unique_length_3_palindromic_subsequences;
pub mod problem_1932_merge_bsts_to_create_single_bst;
pub mod problem_1935_maximum_number_of_words_you_can_type;
pub mod problem_1936_add_minimum_number_of_rungs;
pub mod problem_1937_maximum_number_of_points_with_cost;
Expand Down
105 changes: 105 additions & 0 deletions src/problem_1932_merge_bsts_to_create_single_bst/bfs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
use crate::data_structures::TreeNode;

pub struct Solution;

// ------------------------------------------------------ snip ------------------------------------------------------ //

use std::cell::RefCell;
use std::collections::{HashMap, HashSet, VecDeque};
use std::mem;
use std::rc::Rc;

impl Solution {
fn validate_binary_tree_option(prev: i32, node: &Option<Rc<RefCell<TreeNode>>>) -> Option<i32> {
node.as_ref()
.map_or(Some(prev), |node| Self::validate_binary_tree(prev, node))
}

fn validate_binary_tree(mut prev: i32, node: &Rc<RefCell<TreeNode>>) -> Option<i32> {
let node = node.borrow();
let node = &*node;

prev = Self::validate_binary_tree_option(prev, &node.left)?;

if prev < node.val {
Self::validate_binary_tree_option(node.val, &node.right)
} else {
None
}
}

pub fn can_merge(trees: Vec<Option<Rc<RefCell<TreeNode>>>>) -> Option<Rc<RefCell<TreeNode>>> {
let trees = trees.into_iter().flatten().collect::<Vec<_>>();
let mut nodes = HashMap::new();
let mut non_roots = HashSet::new();

for tree in &trees {
let tree_holder = tree.borrow();
let tree_ref = &*tree_holder;

for child in [&tree_ref.left, &tree_ref.right].into_iter().flatten() {
if !non_roots.insert(child.borrow().val) {
return None;
}
}

let tree_val = tree_ref.val;

drop(tree_holder);

nodes.insert(tree_val, Rc::clone(tree));
}

nodes
.keys()
.copied()
.find(|key| !non_roots.contains(key))
.and_then(|root_val| {
let root = nodes.remove(&root_val).unwrap();
let mut queue = VecDeque::from([Rc::clone(&root)]);

loop {
for _ in 0..queue.len() {
let node = queue.pop_front().unwrap();
let mut node = node.borrow_mut();
let node = &mut *node;

for child in [&mut node.left, &mut node.right].into_iter().flatten() {
let child_val = child.borrow().val;

if let Some(real_child) = nodes.remove(&child_val) {
drop(mem::replace(child, Rc::clone(&real_child)));
queue.push_back(real_child);
}
}
}

if queue.is_empty() {
break;
}
}

if !nodes.is_empty() {
return None;
}

Self::validate_binary_tree(i32::MIN, &root).map(|_| root)
})
}
}

// ------------------------------------------------------ snip ------------------------------------------------------ //

impl super::Solution for Solution {
fn can_merge(trees: Vec<Option<Rc<RefCell<TreeNode>>>>) -> Option<Rc<RefCell<TreeNode>>> {
Self::can_merge(trees)
}
}

#[cfg(test)]
mod tests {
#[test]
fn test_solution() {
super::super::tests::run::<super::Solution>();
}
}
54 changes: 54 additions & 0 deletions src/problem_1932_merge_bsts_to_create_single_bst/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use crate::data_structures::TreeNode;
use std::cell::RefCell;
use std::rc::Rc;

pub mod bfs;

pub trait Solution {
fn can_merge(trees: Vec<Option<Rc<RefCell<TreeNode>>>>) -> Option<Rc<RefCell<TreeNode>>>;
}

#[cfg(test)]
mod tests {
use super::Solution;
use crate::test_utilities;

pub fn run<S: Solution>() {
let test_cases = [
(
&[
&[Some(2), Some(1)] as &[_],
&[Some(3), Some(2), Some(5)],
&[Some(5), Some(4)],
] as &[&[_]],
&[Some(3), Some(2), Some(5), Some(1), None, Some(4)] as &[_],
),
(&[&[Some(5), Some(3), Some(8)], &[Some(3), Some(2), Some(6)]], &[]),
(&[&[Some(5), Some(4)], &[Some(3)]], &[]),
(
&[
&[Some(4), Some(1)],
&[Some(1), None, Some(2)],
&[Some(2), None, Some(3)],
],
&[Some(4), Some(1), None, None, Some(2), None, Some(3)],
),
(
&[&[Some(1), None, Some(3)], &[Some(3), Some(1)], &[Some(4), Some(2)]],
&[],
),
];

for (trees, expected) in test_cases {
assert_eq!(
S::can_merge(
trees
.iter()
.map(|tree| test_utilities::make_tree(tree.iter().copied()))
.collect(),
),
test_utilities::make_tree(expected.iter().copied()),
);
}
}
}

0 comments on commit d502b21

Please sign in to comment.