diff --git a/solution/0100-0199/0105.Construct Binary Tree from Preorder and Inorder Traversal/README.md b/solution/0100-0199/0105.Construct Binary Tree from Preorder and Inorder Traversal/README.md index 5aade841fba9d..0bbc0205057ba 100644 --- a/solution/0100-0199/0105.Construct Binary Tree from Preorder and Inorder Traversal/README.md +++ b/solution/0100-0199/0105.Construct Binary Tree from Preorder and Inorder Traversal/README.md @@ -40,19 +40,22 @@ ## 解法 -### 方法一:递归 +### 方法一:哈希表 + 递归 -前序序列的第一个结点 $preorder[0]$ 为根节点,我们在中序序列中找到根节点的位置 $i$,可以将中序序列划分为左子树 $inorder[0..i]$ 、右子树 $inorder[i+1..]$。 +前序序列的第一个节点 $preorder[0]$ 为根节点,我们在中序序列中找到根节点的位置 $k$,可以将中序序列划分为左子树 $inorder[0..k]$ 、右子树 $inorder[k+1..]$。 -通过左右子树的区间,可以计算出左、右子树节点的个数,假设为 $m$ 和 $n$。然后在前序节点中,从根节点往后的 $m$ 个节点为左子树,再往后的 $n$ 个节点为右子树。 +通过左右子树的区间,可以计算出左、右子树节点的个数,假设为 $a$ 和 $b$。然后在前序节点中,从根节点往后的 $a$ 个节点为左子树,再往后的 $b$ 个节点为右子树。 -递归求解即可。 +因此,我们设计一个函数 $dfs(i, j, n)$,其中 $i$ 和 $j$ 分别表示前序序列和中序序列的起始位置,而 $n$ 表示节点个数。函数的返回值是以 $preorder[i..i+n-1]$ 为前序序列,以 $inorder[j..j+n-1]$ 为中序序列构造出的二叉树。 -> 前序遍历:先遍历根节点,再遍历左右子树;中序遍历:先遍历左子树,再遍历根节点,最后遍历右子树。 +函数 $dfs(i, j, n)$ 的执行过程如下: -时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为二叉树节点个数。 +- 如果 $n \leq 0$,说明没有节点,返回空节点。 +- 取出前序序列的第一个节点 $v = preorder[i]$ 作为根节点,然后利用哈希表 $d$ 找到根节点在中序序列中的位置 $k$,那么左子树的节点个数为 $k - j$,右子树的节点个数为 $n - k + j - 1$。 +- 递归构造左子树 $l = dfs(i + 1, j, k - j)$ 和右子树 $r = dfs(i + 1 + k - j, k + 1, n - k + j - 1)$。 +- 最后返回以 $v$ 为根节点且左右子树分别为 $l$ 和 $r$ 的二叉树。 -如果题目中给定的节点值存在重复,那么我们只需要记录每个节点值出现的所有位置,然后递归构建即可。 +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为二叉树节点个数。 <!-- tabs:start --> @@ -65,7 +68,7 @@ # self.right = right class Solution: def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]: - def dfs(i: int, j: int, n: int): + def dfs(i: int, j: int, n: int) -> Optional[TreeNode]: if n <= 0: return None v = preorder[i] @@ -308,7 +311,7 @@ var buildTree = function (preorder, inorder) { <!-- tabs:end --> -### 方法二 +如果题目中给定的节点值存在重复,那么我们只需要记录每个节点值出现的所有位置,然后递归构建出所有可能的二叉树即可。 <!-- tabs:start --> diff --git a/solution/0100-0199/0105.Construct Binary Tree from Preorder and Inorder Traversal/README_EN.md b/solution/0100-0199/0105.Construct Binary Tree from Preorder and Inorder Traversal/README_EN.md index 0e410b2878022..57e3fe44c481b 100644 --- a/solution/0100-0199/0105.Construct Binary Tree from Preorder and Inorder Traversal/README_EN.md +++ b/solution/0100-0199/0105.Construct Binary Tree from Preorder and Inorder Traversal/README_EN.md @@ -36,19 +36,22 @@ ## Solutions -### Solution 1: Recursion +### Solution 1: Hash Table + Recursion -The first node $preorder[0]$ in the preorder sequence is the root node. We find the position $i$ of the root node in the inorder sequence, which divides the inorder sequence into the left subtree $inorder[0..i]$ and the right subtree $inorder[i+1..]$. +The first node $preorder[0]$ in the pre-order sequence is the root node. We find the position $k$ of the root node in the in-order sequence, which can divide the in-order sequence into the left subtree $inorder[0..k]$ and the right subtree $inorder[k+1..]$. -Through the intervals of the left and right subtrees, we can calculate the number of nodes in the left and right subtrees, assumed to be $m$ and $n$ respectively. Then in the preorder nodes, the $m$ nodes following the root node are the left subtree, and the $n$ nodes after that are the right subtree. +Through the intervals of the left and right subtrees, we can calculate the number of nodes in the left and right subtrees, assumed to be $a$ and $b$. Then in the pre-order nodes, the $a$ nodes after the root node are the left subtree, and the $b$ nodes after that are the right subtree. -We can solve this recursively. +Therefore, we design a function $dfs(i, j, n)$, where $i$ and $j$ represent the starting positions of the pre-order sequence and the in-order sequence, respectively, and $n$ represents the number of nodes. The return value of the function is the binary tree constructed with $preorder[i..i+n-1]$ as the pre-order sequence and $inorder[j..j+n-1]$ as the in-order sequence. -> Preorder traversal: traverse the root node first, then traverse the left and right subtrees; Inorder traversal: traverse the left subtree first, then traverse the root node, and finally traverse the right subtree. +The execution process of the function $dfs(i, j, n)$ is as follows: -The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the number of nodes in the binary tree. +- If $n \leq 0$, it means there are no nodes, return a null node. +- Take out the first node $v = preorder[i]$ of the pre-order sequence as the root node, and then use the hash table $d$ to find the position $k$ of the root node in the in-order sequence. Then the number of nodes in the left subtree is $k - j$, and the number of nodes in the right subtree is $n - k + j - 1$. +- Recursively construct the left subtree $l = dfs(i + 1, j, k - j)$ and the right subtree $r = dfs(i + 1 + k - j, k + 1, n - k + j - 1)$. +- Finally, return the binary tree with $v$ as the root node and $l$ and $r$ as the left and right subtrees, respectively. -If the node values given in the problem have duplicates, then we only need to record all the positions where each node value appears, and then recursively construct the tree. +The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the number of nodes in the binary tree. <!-- tabs:start --> @@ -61,7 +64,7 @@ If the node values given in the problem have duplicates, then we only need to re # self.right = right class Solution: def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]: - def dfs(i: int, j: int, n: int): + def dfs(i: int, j: int, n: int) -> Optional[TreeNode]: if n <= 0: return None v = preorder[i] @@ -304,7 +307,7 @@ var buildTree = function (preorder, inorder) { <!-- tabs:end --> -### Solution 2 +If the node values given in the problem have duplicates, then we only need to record all the positions where each node value appears, and then recursively construct the tree. <!-- tabs:start --> diff --git a/solution/0100-0199/0105.Construct Binary Tree from Preorder and Inorder Traversal/Solution.py b/solution/0100-0199/0105.Construct Binary Tree from Preorder and Inorder Traversal/Solution.py index 3cd2c6d228e58..ebd2eaff5b5a5 100644 --- a/solution/0100-0199/0105.Construct Binary Tree from Preorder and Inorder Traversal/Solution.py +++ b/solution/0100-0199/0105.Construct Binary Tree from Preorder and Inorder Traversal/Solution.py @@ -6,7 +6,7 @@ # self.right = right class Solution: def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]: - def dfs(i: int, j: int, n: int): + def dfs(i: int, j: int, n: int) -> Optional[TreeNode]: if n <= 0: return None v = preorder[i] diff --git a/solution/0100-0199/0106.Construct Binary Tree from Inorder and Postorder Traversal/README.md b/solution/0100-0199/0106.Construct Binary Tree from Inorder and Postorder Traversal/README.md index f909bca455d93..1271e3119ba60 100644 --- a/solution/0100-0199/0106.Construct Binary Tree from Inorder and Postorder Traversal/README.md +++ b/solution/0100-0199/0106.Construct Binary Tree from Inorder and Postorder Traversal/README.md @@ -40,9 +40,15 @@ ## 解法 -### 方法一:递归 +### 方法一:哈希表 + 递归 -思路同 [105. 从前序与中序遍历序列构造二叉树](https://github.com/doocs/leetcode/blob/main/solution/0100-0199/0105.Construct%20Binary%20Tree%20from%20Preorder%20and%20Inorder%20Traversal/README.md)。 +后序遍历的最后一个节点是根节点,我们可以根据这个特点找到根节点在中序遍历中的位置,然后递归地构造左右子树。 + +具体地,我们先用一个哈希表 $d$ 存储中序遍历中每个节点的位置。然后我们设计一个递归函数 $dfs(i, j, n)$,其中 $i$ 和 $j$ 分别表示中序遍历和后序遍历的起点,而 $n$ 表示子树包含的节点数。函数的逻辑如下: + +- 如果 $n \leq 0$,说明子树为空,返回空节点。 +- 否则,取出后序遍历的最后一个节点 $v$,然后我们在哈希表 $d$ 中找到 $v$ 在中序遍历中的位置,设为 $k$。那么左子树包含的节点数为 $k - i$,右子树包含的节点数为 $n - k + i - 1$。 +- 递归构造左子树 $dfs(i, j, k - i)$ 和右子树 $dfs(k + 1, j + k - i, n - k + i - 1)$,并连接到根节点上,最后返回根节点。 时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是二叉树的节点个数。 @@ -56,15 +62,18 @@ # self.left = left # self.right = right class Solution: - def buildTree(self, inorder: List[int], postorder: List[int]) -> TreeNode: - if not postorder: - return None - v = postorder[-1] - root = TreeNode(val=v) - i = inorder.index(v) - root.left = self.buildTree(inorder[:i], postorder[:i]) - root.right = self.buildTree(inorder[i + 1 :], postorder[i:-1]) - return root + def buildTree(self, inorder: List[int], postorder: List[int]) -> Optional[TreeNode]: + def dfs(i: int, j: int, n: int) -> Optional[TreeNode]: + if n <= 0: + return None + v = postorder[j + n - 1] + k = d[v] + l = dfs(i, j, k - i) + r = dfs(k + 1, j + k - i, n - k + i - 1) + return TreeNode(v, l, r) + + d = {v: i for i, v in enumerate(inorder)} + return dfs(0, 0, len(inorder)) ``` ```java @@ -84,25 +93,29 @@ class Solution: * } */ class Solution { - private Map<Integer, Integer> indexes = new HashMap<>(); + private Map<Integer, Integer> d = new HashMap<>(); + private int[] inorder; + private int[] postorder; public TreeNode buildTree(int[] inorder, int[] postorder) { - for (int i = 0; i < inorder.length; ++i) { - indexes.put(inorder[i], i); + this.inorder = inorder; + this.postorder = postorder; + int n = inorder.length; + for (int i = 0; i < n; ++i) { + d.put(inorder[i], i); } - return dfs(inorder, postorder, 0, 0, inorder.length); + return dfs(0, 0, n); } - private TreeNode dfs(int[] inorder, int[] postorder, int i, int j, int n) { + private TreeNode dfs(int i, int j, int n) { if (n <= 0) { return null; } int v = postorder[j + n - 1]; - int k = indexes.get(v); - TreeNode root = new TreeNode(v); - root.left = dfs(inorder, postorder, i, j, k - i); - root.right = dfs(inorder, postorder, k + 1, j + k - i, n - k + i - 1); - return root; + int k = d.get(v); + TreeNode l = dfs(i, j, k - i); + TreeNode r = dfs(k + 1, j + k - i, n - k + i - 1); + return new TreeNode(v, l, r); } } ``` @@ -121,21 +134,23 @@ class Solution { */ class Solution { public: - unordered_map<int, int> indexes; - TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) { - for (int i = 0; i < inorder.size(); ++i) indexes[inorder[i]] = i; - return dfs(inorder, postorder, 0, 0, inorder.size()); - } - - TreeNode* dfs(vector<int>& inorder, vector<int>& postorder, int i, int j, int n) { - if (n <= 0) return nullptr; - int v = postorder[j + n - 1]; - int k = indexes[v]; - TreeNode* root = new TreeNode(v); - root->left = dfs(inorder, postorder, i, j, k - i); - root->right = dfs(inorder, postorder, k + 1, j + k - i, n - k + i - 1); - return root; + unordered_map<int, int> d; + int n = inorder.size(); + for (int i = 0; i < n; ++i) { + d[inorder[i]] = i; + } + function<TreeNode*(int, int, int)> dfs = [&](int i, int j, int n) -> TreeNode* { + if (n <= 0) { + return nullptr; + } + int v = postorder[j + n - 1]; + int k = d[v]; + auto l = dfs(i, j, k - i); + auto r = dfs(k + 1, j + k - i, n - k + i - 1); + return new TreeNode(v, l, r); + }; + return dfs(0, 0, n); } }; ``` @@ -150,9 +165,9 @@ public: * } */ func buildTree(inorder []int, postorder []int) *TreeNode { - indexes := make(map[int]int) + d := map[int]int{} for i, v := range inorder { - indexes[v] = i + d[v] = i } var dfs func(i, j, n int) *TreeNode dfs = func(i, j, n int) *TreeNode { @@ -160,11 +175,10 @@ func buildTree(inorder []int, postorder []int) *TreeNode { return nil } v := postorder[j+n-1] - k := indexes[v] - root := &TreeNode{Val: v} - root.Left = dfs(i, j, k-i) - root.Right = dfs(k+1, j+k-i, n-k+i-1) - return root + k := d[v] + l := dfs(i, j, k-i) + r := dfs(k+1, j+k-i, n-k+i-1) + return &TreeNode{v, l, r} } return dfs(0, 0, len(inorder)) } @@ -186,17 +200,22 @@ func buildTree(inorder []int, postorder []int) *TreeNode { */ function buildTree(inorder: number[], postorder: number[]): TreeNode | null { - const n = postorder.length; - if (n == 0) { - return null; + const n = inorder.length; + const d: Record<number, number> = {}; + for (let i = 0; i < n; i++) { + d[inorder[i]] = i; } - const val = postorder[n - 1]; - const index = inorder.indexOf(val); - return new TreeNode( - val, - buildTree(inorder.slice(0, index), postorder.slice(0, index)), - buildTree(inorder.slice(index + 1), postorder.slice(index, n - 1)), - ); + const dfs = (i: number, j: number, n: number): TreeNode | null => { + if (n <= 0) { + return null; + } + const v = postorder[j + n - 1]; + const k = d[v]; + const l = dfs(i, j, k - i); + const r = dfs(k + 1, j + k - i, n - 1 - (k - i)); + return new TreeNode(v, l, r); + }; + return dfs(0, 0, n); } ``` @@ -221,51 +240,32 @@ function buildTree(inorder: number[], postorder: number[]): TreeNode | null { // } use std::rc::Rc; use std::cell::RefCell; +use std::collections::HashMap; impl Solution { - fn reset( - inorder: &Vec<i32>, - i_left: usize, - i_right: usize, - postorder: &Vec<i32>, - p_left: usize, - p_right: usize - ) -> Option<Rc<RefCell<TreeNode>>> { - if i_left == i_right { - return None; - } - let val = postorder[p_right - 1]; - let index = inorder - .iter() - .position(|&v| v == val) - .unwrap(); - Some( - Rc::new( - RefCell::new(TreeNode { - val, - left: Self::reset( - inorder, - i_left, - index, - postorder, - p_left, - p_left + index - i_left - ), - right: Self::reset( - inorder, - index + 1, - i_right, - postorder, - p_left + index - i_left, - p_right - 1 - ), - }) - ) - ) - } - pub fn build_tree(inorder: Vec<i32>, postorder: Vec<i32>) -> Option<Rc<RefCell<TreeNode>>> { let n = inorder.len(); - Self::reset(&inorder, 0, n, &postorder, 0, n) + let mut d: HashMap<i32, usize> = HashMap::new(); + for i in 0..n { + d.insert(inorder[i], i); + } + fn dfs( + inorder: &[i32], + postorder: &[i32], + d: &HashMap<i32, usize>, + i: usize, + j: usize, + n: usize + ) -> Option<Rc<RefCell<TreeNode>>> { + if n <= 0 { + return None; + } + let v = postorder[j + n - 1]; + let k = *d.get(&v).unwrap(); + let l = dfs(inorder, postorder, d, i, j, k - i); + let r = dfs(inorder, postorder, d, k + 1, j + k - i, n - 1 - (k - i)); + Some(Rc::new(RefCell::new(TreeNode { val: v, left: l, right: r }))) + } + dfs(&inorder, &postorder, &d, 0, 0, n) } } ``` diff --git a/solution/0100-0199/0106.Construct Binary Tree from Inorder and Postorder Traversal/README_EN.md b/solution/0100-0199/0106.Construct Binary Tree from Inorder and Postorder Traversal/README_EN.md index c51ab91208fc1..a04b251875862 100644 --- a/solution/0100-0199/0106.Construct Binary Tree from Inorder and Postorder Traversal/README_EN.md +++ b/solution/0100-0199/0106.Construct Binary Tree from Inorder and Postorder Traversal/README_EN.md @@ -36,9 +36,15 @@ ## Solutions -### Solution 1: Recursion +### Solution 1: Hash Table + Recursion -The approach is the same as in [105. Construct Binary Tree from Preorder and Inorder Traversal](https://github.com/doocs/leetcode/blob/main/solution/0100-0199/0105.Construct%20Binary%20Tree%20from%20Preorder%20and%20Inorder%20Traversal/README_EN.md). +The last node in the post-order traversal is the root node. We can find the position of the root node in the in-order traversal, and then recursively construct the left and right subtrees. + +Specifically, we first use a hash table $d$ to store the position of each node in the in-order traversal. Then we design a recursive function $dfs(i, j, n)$, where $i$ and $j$ represent the starting positions of the in-order and post-order traversals, respectively, and $n$ represents the number of nodes in the subtree. The function logic is as follows: + +- If $n \leq 0$, it means the subtree is empty, return a null node. +- Otherwise, take out the last node $v$ of the post-order traversal, and then find the position $k$ of $v$ in the in-order traversal using the hash table $d$. Then the number of nodes in the left subtree is $k - i$, and the number of nodes in the right subtree is $n - k + i - 1$. +- Recursively construct the left subtree $dfs(i, j, k - i)$ and the right subtree $dfs(k + 1, j + k - i, n - k + i - 1)$, connect them to the root node, and finally return the root node. The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the number of nodes in the binary tree. @@ -52,15 +58,18 @@ The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is # self.left = left # self.right = right class Solution: - def buildTree(self, inorder: List[int], postorder: List[int]) -> TreeNode: - if not postorder: - return None - v = postorder[-1] - root = TreeNode(val=v) - i = inorder.index(v) - root.left = self.buildTree(inorder[:i], postorder[:i]) - root.right = self.buildTree(inorder[i + 1 :], postorder[i:-1]) - return root + def buildTree(self, inorder: List[int], postorder: List[int]) -> Optional[TreeNode]: + def dfs(i: int, j: int, n: int) -> Optional[TreeNode]: + if n <= 0: + return None + v = postorder[j + n - 1] + k = d[v] + l = dfs(i, j, k - i) + r = dfs(k + 1, j + k - i, n - k + i - 1) + return TreeNode(v, l, r) + + d = {v: i for i, v in enumerate(inorder)} + return dfs(0, 0, len(inorder)) ``` ```java @@ -80,25 +89,29 @@ class Solution: * } */ class Solution { - private Map<Integer, Integer> indexes = new HashMap<>(); + private Map<Integer, Integer> d = new HashMap<>(); + private int[] inorder; + private int[] postorder; public TreeNode buildTree(int[] inorder, int[] postorder) { - for (int i = 0; i < inorder.length; ++i) { - indexes.put(inorder[i], i); + this.inorder = inorder; + this.postorder = postorder; + int n = inorder.length; + for (int i = 0; i < n; ++i) { + d.put(inorder[i], i); } - return dfs(inorder, postorder, 0, 0, inorder.length); + return dfs(0, 0, n); } - private TreeNode dfs(int[] inorder, int[] postorder, int i, int j, int n) { + private TreeNode dfs(int i, int j, int n) { if (n <= 0) { return null; } int v = postorder[j + n - 1]; - int k = indexes.get(v); - TreeNode root = new TreeNode(v); - root.left = dfs(inorder, postorder, i, j, k - i); - root.right = dfs(inorder, postorder, k + 1, j + k - i, n - k + i - 1); - return root; + int k = d.get(v); + TreeNode l = dfs(i, j, k - i); + TreeNode r = dfs(k + 1, j + k - i, n - k + i - 1); + return new TreeNode(v, l, r); } } ``` @@ -117,21 +130,23 @@ class Solution { */ class Solution { public: - unordered_map<int, int> indexes; - TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) { - for (int i = 0; i < inorder.size(); ++i) indexes[inorder[i]] = i; - return dfs(inorder, postorder, 0, 0, inorder.size()); - } - - TreeNode* dfs(vector<int>& inorder, vector<int>& postorder, int i, int j, int n) { - if (n <= 0) return nullptr; - int v = postorder[j + n - 1]; - int k = indexes[v]; - TreeNode* root = new TreeNode(v); - root->left = dfs(inorder, postorder, i, j, k - i); - root->right = dfs(inorder, postorder, k + 1, j + k - i, n - k + i - 1); - return root; + unordered_map<int, int> d; + int n = inorder.size(); + for (int i = 0; i < n; ++i) { + d[inorder[i]] = i; + } + function<TreeNode*(int, int, int)> dfs = [&](int i, int j, int n) -> TreeNode* { + if (n <= 0) { + return nullptr; + } + int v = postorder[j + n - 1]; + int k = d[v]; + auto l = dfs(i, j, k - i); + auto r = dfs(k + 1, j + k - i, n - k + i - 1); + return new TreeNode(v, l, r); + }; + return dfs(0, 0, n); } }; ``` @@ -146,9 +161,9 @@ public: * } */ func buildTree(inorder []int, postorder []int) *TreeNode { - indexes := make(map[int]int) + d := map[int]int{} for i, v := range inorder { - indexes[v] = i + d[v] = i } var dfs func(i, j, n int) *TreeNode dfs = func(i, j, n int) *TreeNode { @@ -156,11 +171,10 @@ func buildTree(inorder []int, postorder []int) *TreeNode { return nil } v := postorder[j+n-1] - k := indexes[v] - root := &TreeNode{Val: v} - root.Left = dfs(i, j, k-i) - root.Right = dfs(k+1, j+k-i, n-k+i-1) - return root + k := d[v] + l := dfs(i, j, k-i) + r := dfs(k+1, j+k-i, n-k+i-1) + return &TreeNode{v, l, r} } return dfs(0, 0, len(inorder)) } @@ -182,17 +196,22 @@ func buildTree(inorder []int, postorder []int) *TreeNode { */ function buildTree(inorder: number[], postorder: number[]): TreeNode | null { - const n = postorder.length; - if (n == 0) { - return null; + const n = inorder.length; + const d: Record<number, number> = {}; + for (let i = 0; i < n; i++) { + d[inorder[i]] = i; } - const val = postorder[n - 1]; - const index = inorder.indexOf(val); - return new TreeNode( - val, - buildTree(inorder.slice(0, index), postorder.slice(0, index)), - buildTree(inorder.slice(index + 1), postorder.slice(index, n - 1)), - ); + const dfs = (i: number, j: number, n: number): TreeNode | null => { + if (n <= 0) { + return null; + } + const v = postorder[j + n - 1]; + const k = d[v]; + const l = dfs(i, j, k - i); + const r = dfs(k + 1, j + k - i, n - 1 - (k - i)); + return new TreeNode(v, l, r); + }; + return dfs(0, 0, n); } ``` @@ -217,51 +236,32 @@ function buildTree(inorder: number[], postorder: number[]): TreeNode | null { // } use std::rc::Rc; use std::cell::RefCell; +use std::collections::HashMap; impl Solution { - fn reset( - inorder: &Vec<i32>, - i_left: usize, - i_right: usize, - postorder: &Vec<i32>, - p_left: usize, - p_right: usize - ) -> Option<Rc<RefCell<TreeNode>>> { - if i_left == i_right { - return None; - } - let val = postorder[p_right - 1]; - let index = inorder - .iter() - .position(|&v| v == val) - .unwrap(); - Some( - Rc::new( - RefCell::new(TreeNode { - val, - left: Self::reset( - inorder, - i_left, - index, - postorder, - p_left, - p_left + index - i_left - ), - right: Self::reset( - inorder, - index + 1, - i_right, - postorder, - p_left + index - i_left, - p_right - 1 - ), - }) - ) - ) - } - pub fn build_tree(inorder: Vec<i32>, postorder: Vec<i32>) -> Option<Rc<RefCell<TreeNode>>> { let n = inorder.len(); - Self::reset(&inorder, 0, n, &postorder, 0, n) + let mut d: HashMap<i32, usize> = HashMap::new(); + for i in 0..n { + d.insert(inorder[i], i); + } + fn dfs( + inorder: &[i32], + postorder: &[i32], + d: &HashMap<i32, usize>, + i: usize, + j: usize, + n: usize + ) -> Option<Rc<RefCell<TreeNode>>> { + if n <= 0 { + return None; + } + let v = postorder[j + n - 1]; + let k = *d.get(&v).unwrap(); + let l = dfs(inorder, postorder, d, i, j, k - i); + let r = dfs(inorder, postorder, d, k + 1, j + k - i, n - 1 - (k - i)); + Some(Rc::new(RefCell::new(TreeNode { val: v, left: l, right: r }))) + } + dfs(&inorder, &postorder, &d, 0, 0, n) } } ``` diff --git a/solution/0100-0199/0106.Construct Binary Tree from Inorder and Postorder Traversal/Solution.cpp b/solution/0100-0199/0106.Construct Binary Tree from Inorder and Postorder Traversal/Solution.cpp index 203e17b51e3cc..bdfd4485910d8 100644 --- a/solution/0100-0199/0106.Construct Binary Tree from Inorder and Postorder Traversal/Solution.cpp +++ b/solution/0100-0199/0106.Construct Binary Tree from Inorder and Postorder Traversal/Solution.cpp @@ -11,20 +11,22 @@ */ class Solution { public: - unordered_map<int, int> indexes; - TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) { - for (int i = 0; i < inorder.size(); ++i) indexes[inorder[i]] = i; - return dfs(inorder, postorder, 0, 0, inorder.size()); - } - - TreeNode* dfs(vector<int>& inorder, vector<int>& postorder, int i, int j, int n) { - if (n <= 0) return nullptr; - int v = postorder[j + n - 1]; - int k = indexes[v]; - TreeNode* root = new TreeNode(v); - root->left = dfs(inorder, postorder, i, j, k - i); - root->right = dfs(inorder, postorder, k + 1, j + k - i, n - k + i - 1); - return root; + unordered_map<int, int> d; + int n = inorder.size(); + for (int i = 0; i < n; ++i) { + d[inorder[i]] = i; + } + function<TreeNode*(int, int, int)> dfs = [&](int i, int j, int n) -> TreeNode* { + if (n <= 0) { + return nullptr; + } + int v = postorder[j + n - 1]; + int k = d[v]; + auto l = dfs(i, j, k - i); + auto r = dfs(k + 1, j + k - i, n - k + i - 1); + return new TreeNode(v, l, r); + }; + return dfs(0, 0, n); } }; \ No newline at end of file diff --git a/solution/0100-0199/0106.Construct Binary Tree from Inorder and Postorder Traversal/Solution.go b/solution/0100-0199/0106.Construct Binary Tree from Inorder and Postorder Traversal/Solution.go index d40078cd384a4..e9e4ad32b53d2 100644 --- a/solution/0100-0199/0106.Construct Binary Tree from Inorder and Postorder Traversal/Solution.go +++ b/solution/0100-0199/0106.Construct Binary Tree from Inorder and Postorder Traversal/Solution.go @@ -7,9 +7,9 @@ * } */ func buildTree(inorder []int, postorder []int) *TreeNode { - indexes := make(map[int]int) + d := map[int]int{} for i, v := range inorder { - indexes[v] = i + d[v] = i } var dfs func(i, j, n int) *TreeNode dfs = func(i, j, n int) *TreeNode { @@ -17,11 +17,10 @@ func buildTree(inorder []int, postorder []int) *TreeNode { return nil } v := postorder[j+n-1] - k := indexes[v] - root := &TreeNode{Val: v} - root.Left = dfs(i, j, k-i) - root.Right = dfs(k+1, j+k-i, n-k+i-1) - return root + k := d[v] + l := dfs(i, j, k-i) + r := dfs(k+1, j+k-i, n-k+i-1) + return &TreeNode{v, l, r} } return dfs(0, 0, len(inorder)) } \ No newline at end of file diff --git a/solution/0100-0199/0106.Construct Binary Tree from Inorder and Postorder Traversal/Solution.java b/solution/0100-0199/0106.Construct Binary Tree from Inorder and Postorder Traversal/Solution.java index d9b2304aee731..d40b90a3df4ac 100644 --- a/solution/0100-0199/0106.Construct Binary Tree from Inorder and Postorder Traversal/Solution.java +++ b/solution/0100-0199/0106.Construct Binary Tree from Inorder and Postorder Traversal/Solution.java @@ -14,24 +14,28 @@ * } */ class Solution { - private Map<Integer, Integer> indexes = new HashMap<>(); + private Map<Integer, Integer> d = new HashMap<>(); + private int[] inorder; + private int[] postorder; public TreeNode buildTree(int[] inorder, int[] postorder) { - for (int i = 0; i < inorder.length; ++i) { - indexes.put(inorder[i], i); + this.inorder = inorder; + this.postorder = postorder; + int n = inorder.length; + for (int i = 0; i < n; ++i) { + d.put(inorder[i], i); } - return dfs(inorder, postorder, 0, 0, inorder.length); + return dfs(0, 0, n); } - private TreeNode dfs(int[] inorder, int[] postorder, int i, int j, int n) { + private TreeNode dfs(int i, int j, int n) { if (n <= 0) { return null; } int v = postorder[j + n - 1]; - int k = indexes.get(v); - TreeNode root = new TreeNode(v); - root.left = dfs(inorder, postorder, i, j, k - i); - root.right = dfs(inorder, postorder, k + 1, j + k - i, n - k + i - 1); - return root; + int k = d.get(v); + TreeNode l = dfs(i, j, k - i); + TreeNode r = dfs(k + 1, j + k - i, n - k + i - 1); + return new TreeNode(v, l, r); } } \ No newline at end of file diff --git a/solution/0100-0199/0106.Construct Binary Tree from Inorder and Postorder Traversal/Solution.py b/solution/0100-0199/0106.Construct Binary Tree from Inorder and Postorder Traversal/Solution.py index 5badcffe7da00..676b2afcc9208 100644 --- a/solution/0100-0199/0106.Construct Binary Tree from Inorder and Postorder Traversal/Solution.py +++ b/solution/0100-0199/0106.Construct Binary Tree from Inorder and Postorder Traversal/Solution.py @@ -5,12 +5,15 @@ # self.left = left # self.right = right class Solution: - def buildTree(self, inorder: List[int], postorder: List[int]) -> TreeNode: - if not postorder: - return None - v = postorder[-1] - root = TreeNode(val=v) - i = inorder.index(v) - root.left = self.buildTree(inorder[:i], postorder[:i]) - root.right = self.buildTree(inorder[i + 1 :], postorder[i:-1]) - return root + def buildTree(self, inorder: List[int], postorder: List[int]) -> Optional[TreeNode]: + def dfs(i: int, j: int, n: int) -> Optional[TreeNode]: + if n <= 0: + return None + v = postorder[j + n - 1] + k = d[v] + l = dfs(i, j, k - i) + r = dfs(k + 1, j + k - i, n - k + i - 1) + return TreeNode(v, l, r) + + d = {v: i for i, v in enumerate(inorder)} + return dfs(0, 0, len(inorder)) diff --git a/solution/0100-0199/0106.Construct Binary Tree from Inorder and Postorder Traversal/Solution.rs b/solution/0100-0199/0106.Construct Binary Tree from Inorder and Postorder Traversal/Solution.rs index 110cd8c554124..fb35b215d6887 100644 --- a/solution/0100-0199/0106.Construct Binary Tree from Inorder and Postorder Traversal/Solution.rs +++ b/solution/0100-0199/0106.Construct Binary Tree from Inorder and Postorder Traversal/Solution.rs @@ -18,50 +18,31 @@ // } use std::rc::Rc; use std::cell::RefCell; +use std::collections::HashMap; impl Solution { - fn reset( - inorder: &Vec<i32>, - i_left: usize, - i_right: usize, - postorder: &Vec<i32>, - p_left: usize, - p_right: usize - ) -> Option<Rc<RefCell<TreeNode>>> { - if i_left == i_right { - return None; - } - let val = postorder[p_right - 1]; - let index = inorder - .iter() - .position(|&v| v == val) - .unwrap(); - Some( - Rc::new( - RefCell::new(TreeNode { - val, - left: Self::reset( - inorder, - i_left, - index, - postorder, - p_left, - p_left + index - i_left - ), - right: Self::reset( - inorder, - index + 1, - i_right, - postorder, - p_left + index - i_left, - p_right - 1 - ), - }) - ) - ) - } - pub fn build_tree(inorder: Vec<i32>, postorder: Vec<i32>) -> Option<Rc<RefCell<TreeNode>>> { let n = inorder.len(); - Self::reset(&inorder, 0, n, &postorder, 0, n) + let mut d: HashMap<i32, usize> = HashMap::new(); + for i in 0..n { + d.insert(inorder[i], i); + } + fn dfs( + inorder: &[i32], + postorder: &[i32], + d: &HashMap<i32, usize>, + i: usize, + j: usize, + n: usize + ) -> Option<Rc<RefCell<TreeNode>>> { + if n <= 0 { + return None; + } + let v = postorder[j + n - 1]; + let k = *d.get(&v).unwrap(); + let l = dfs(inorder, postorder, d, i, j, k - i); + let r = dfs(inorder, postorder, d, k + 1, j + k - i, n - 1 - (k - i)); + Some(Rc::new(RefCell::new(TreeNode { val: v, left: l, right: r }))) + } + dfs(&inorder, &postorder, &d, 0, 0, n) } } diff --git a/solution/0100-0199/0106.Construct Binary Tree from Inorder and Postorder Traversal/Solution.ts b/solution/0100-0199/0106.Construct Binary Tree from Inorder and Postorder Traversal/Solution.ts index edba4db0981c3..6c5fd5ab54d89 100644 --- a/solution/0100-0199/0106.Construct Binary Tree from Inorder and Postorder Traversal/Solution.ts +++ b/solution/0100-0199/0106.Construct Binary Tree from Inorder and Postorder Traversal/Solution.ts @@ -13,15 +13,20 @@ */ function buildTree(inorder: number[], postorder: number[]): TreeNode | null { - const n = postorder.length; - if (n == 0) { - return null; + const n = inorder.length; + const d: Record<number, number> = {}; + for (let i = 0; i < n; i++) { + d[inorder[i]] = i; } - const val = postorder[n - 1]; - const index = inorder.indexOf(val); - return new TreeNode( - val, - buildTree(inorder.slice(0, index), postorder.slice(0, index)), - buildTree(inorder.slice(index + 1), postorder.slice(index, n - 1)), - ); + const dfs = (i: number, j: number, n: number): TreeNode | null => { + if (n <= 0) { + return null; + } + const v = postorder[j + n - 1]; + const k = d[v]; + const l = dfs(i, j, k - i); + const r = dfs(k + 1, j + k - i, n - 1 - (k - i)); + return new TreeNode(v, l, r); + }; + return dfs(0, 0, n); }