|
| 1 | +use datastructure::TreeNode; |
| 2 | +use std::cell::RefCell; |
| 3 | +use std::rc::Rc; |
| 4 | + |
| 5 | +/// [105. 从前序与中序遍历序列构造二叉树](https://leetcode.cn/problems/construct-binary-tree-from-preorder-and-inorder-traversal/) |
| 6 | +/// |
| 7 | +/// ## 思路 |
| 8 | +/// 1. 通过前序知道根节点,然后分割中序得到左右子树 |
| 9 | +/// - 通过中序找到根节点的位置, 然后通过左右子树长度分割前序 |
| 10 | +/// 2. 递归构建左右子树 |
| 11 | +/// - 递归结束条件是前序为空 |
| 12 | +/// 3. 挂载左右子树到根, 然后返回根节点 |
| 13 | +pub fn build_tree(preorder: Vec<i32>, inorder: Vec<i32>) -> Option<Rc<RefCell<TreeNode>>> { |
| 14 | + fn build(preorder: &[i32], inorder: &[i32]) -> Option<Rc<RefCell<TreeNode>>> { |
| 15 | + if preorder.is_empty() { |
| 16 | + return None; |
| 17 | + } |
| 18 | + let root_val = preorder[0]; |
| 19 | + let mut root = TreeNode::new(root_val); |
| 20 | + |
| 21 | + let root_idx = inorder.iter().position(|&x| x == root_val).unwrap(); |
| 22 | + let (inorder_left, inorder_right) = inorder.split_at(root_idx); |
| 23 | + |
| 24 | + let inorder_left_len = inorder_left.len(); |
| 25 | + let (preorder_left, preorder_right) = preorder.split_at(inorder_left_len + 1); |
| 26 | + |
| 27 | + root.left = build(&preorder_left[1..], inorder_left); |
| 28 | + root.right = build(preorder_right, &inorder_right[1..]); |
| 29 | + Some(Rc::new(RefCell::new(root))) |
| 30 | + } |
| 31 | + build(&preorder, &inorder) |
| 32 | +} |
| 33 | + |
| 34 | +#[cfg(test)] |
| 35 | +mod tests { |
| 36 | + use macros::tree; |
| 37 | + |
| 38 | + use super::*; |
| 39 | + |
| 40 | + #[test] |
| 41 | + fn test_build_tree() { |
| 42 | + let preorder = vec![3, 9, 20, 15, 7]; |
| 43 | + let inorder = vec![9, 3, 15, 20, 7]; |
| 44 | + let root = build_tree(preorder, inorder); |
| 45 | + assert_eq!( |
| 46 | + root, |
| 47 | + tree!({3, left: {9}, right:{20, left: {15}, right:{7} }}) |
| 48 | + ); |
| 49 | + } |
| 50 | +} |
0 commit comments