From 0454fdb07768923900b5d7961f05c4b0206b0ed0 Mon Sep 17 00:00:00 2001 From: yanglbme Date: Sun, 11 Feb 2024 11:50:13 +0800 Subject: [PATCH] feat: add solutions to lc problem: No.0145 No.0145.Binary Tree Postorder Traversal --- .../README.md | 360 ++++++++++++------ .../README_EN.md | 360 ++++++++++++------ .../Solution.cpp | 27 +- .../Solution.go | 30 +- .../Solution.java | 3 +- .../Solution.py | 1 - .../Solution.rs | 14 +- .../Solution.ts | 27 +- .../Solution2.cpp | 35 ++ .../Solution2.go | 29 ++ .../Solution2.rs | 43 --- .../Solution2.ts | 16 +- .../Solution3.cpp | 38 ++ .../Solution3.go | 30 ++ .../Solution3.ts | 16 +- 15 files changed, 653 insertions(+), 376 deletions(-) create mode 100644 solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution2.cpp create mode 100644 solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution2.go delete mode 100644 solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution2.rs create mode 100644 solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution3.cpp create mode 100644 solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution3.go diff --git a/solution/0100-0199/0145.Binary Tree Postorder Traversal/README.md b/solution/0100-0199/0145.Binary Tree Postorder Traversal/README.md index 348a8e1ec01d4..5aaadd495a73b 100644 --- a/solution/0100-0199/0145.Binary Tree Postorder Traversal/README.md +++ b/solution/0100-0199/0145.Binary Tree Postorder Traversal/README.md @@ -46,7 +46,11 @@ ## 解法 -### 方法一 +### 方法一:递归 + +我们先递归左右子树,然后再访问根节点。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是二叉树的节点数,空间复杂度主要取决于递归调用的栈空间。 @@ -64,7 +68,6 @@ class Solution: return dfs(root.left) dfs(root.right) - nonlocal ans ans.append(root.val) ans = [] @@ -89,10 +92,9 @@ class Solution: * } */ class Solution { - private List ans; + private List ans = new ArrayList<>(); public List postorderTraversal(TreeNode root) { - ans = new ArrayList<>(); dfs(root); return ans; } @@ -124,26 +126,15 @@ class Solution { public: vector postorderTraversal(TreeNode* root) { vector ans; - while (root) { - if (!root->right) { - ans.push_back(root->val); - root = root->left; - } else { - TreeNode* next = root->right; - while (next->left && next->left != root) { - next = next->left; - } - if (!next->left) { - ans.push_back(root->val); - next->left = root; - root = root->right; - } else { - next->left = nullptr; - root = root->left; - } + function dfs = [&](TreeNode* root) { + if (!root) { + return; } - } - reverse(ans.begin(), ans.end()); + dfs(root->left); + dfs(root->right); + ans.push_back(root->val); + }; + dfs(root); return ans; } }; @@ -158,28 +149,18 @@ public: * Right *TreeNode * } */ -func postorderTraversal(root *TreeNode) []int { - var ans []int - for root != nil { - if root.Right == nil { - ans = append([]int{root.Val}, ans...) - root = root.Left - } else { - next := root.Right - for next.Left != nil && next.Left != root { - next = next.Left - } - if next.Left == nil { - ans = append([]int{root.Val}, ans...) - next.Left = root - root = root.Right - } else { - next.Left = nil - root = root.Left - } +func postorderTraversal(root *TreeNode) (ans []int) { + var dfs func(*TreeNode) + dfs = func(root *TreeNode) { + if root == nil { + return } + dfs(root.Left) + dfs(root.Right) + ans = append(ans, root.Val) } - return ans + dfs(root) + return } ``` @@ -199,25 +180,16 @@ func postorderTraversal(root *TreeNode) []int { */ function postorderTraversal(root: TreeNode | null): number[] { - if (root == null) return []; - let stack = []; - let ans = []; - let prev = null; - while (root || stack.length) { - while (root) { - stack.push(root); - root = root.left; - } - root = stack.pop(); - if (!root.right || root.right == prev) { - ans.push(root.val); - prev = root; - root = null; - } else { - stack.push(root); - root = root.right; + const ans: number[] = []; + const dfs = (root: TreeNode | null) => { + if (!root) { + return; } - } + dfs(root.left); + dfs(root.right); + ans.push(root.val); + }; + dfs(root); return ans; } ``` @@ -244,27 +216,40 @@ function postorderTraversal(root: TreeNode | null): number[] { use std::rc::Rc; use std::cell::RefCell; impl Solution { - fn dfs(root: &Option>>, res: &mut Vec) { + fn dfs(root: &Option>>, ans: &mut Vec) { if root.is_none() { return; } let node = root.as_ref().unwrap().borrow(); - Self::dfs(&node.left, res); - Self::dfs(&node.right, res); - res.push(node.val); + Self::dfs(&node.left, ans); + Self::dfs(&node.right, ans); + ans.push(node.val); } pub fn postorder_traversal(root: Option>>) -> Vec { - let mut res = vec![]; - Self::dfs(&root, &mut res); - res + let mut ans = vec![]; + Self::dfs(&root, &mut ans); + ans } } ``` -### 方法二 +### 方法二:栈实现后序遍历 + +先序遍历的顺序是:根、左、右,如果我们改变左右孩子的顺序,就能将顺序变成:根、右、左。最后再将结果反转一下,就得到了后序遍历的结果。 + +因此,栈实现非递归遍历的思路如下: + +1. 定义一个栈 $stk$,先将根节点压入栈 +1. 若栈不为空,每次从栈中弹出一个节点 +1. 处理该节点 +1. 先把节点左孩子压入栈,接着把节点右孩子压入栈(如果有孩子节点) +1. 重复 2-4 +1. 将结果反转,得到后序遍历的结果 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是二叉树的节点数,空间复杂度主要取决于栈空间。 @@ -330,6 +315,76 @@ class Solution { } ``` +```cpp +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode() : val(0), left(nullptr), right(nullptr) {} + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} + * }; + */ +class Solution { +public: + vector postorderTraversal(TreeNode* root) { + vector ans; + if (!root) { + return ans; + } + stack stk; + stk.push(root); + while (stk.size()) { + auto node = stk.top(); + stk.pop(); + ans.push_back(node->val); + if (node->left) { + stk.push(node->left); + } + if (node->right) { + stk.push(node->right); + } + } + reverse(ans.begin(), ans.end()); + return ans; + } +}; +``` + +```go +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func postorderTraversal(root *TreeNode) (ans []int) { + if root == nil { + return + } + stk := []*TreeNode{root} + for len(stk) > 0 { + node := stk[len(stk)-1] + stk = stk[:len(stk)-1] + ans = append(ans, node.Val) + if node.Left != nil { + stk = append(stk, node.Left) + } + if node.Right != nil { + stk = append(stk, node.Right) + } + } + for i, j := 0, len(ans)-1; i < j; i, j = i+1, j-1 { + ans[i], ans[j] = ans[j], ans[i] + } + return +} +``` + ```ts /** * Definition for a binary tree node. @@ -346,63 +401,40 @@ class Solution { */ function postorderTraversal(root: TreeNode | null): number[] { - if (root == null) { - return []; + const ans: number[] = []; + if (!root) { + return ans; } - const { val, left, right } = root; - return [...postorderTraversal(left), ...postorderTraversal(right), val]; -} -``` - -```rust -// Definition for a binary tree node. -// #[derive(Debug, PartialEq, Eq)] -// pub struct TreeNode { -// pub val: i32, -// pub left: Option>>, -// pub right: Option>>, -// } -// -// impl TreeNode { -// #[inline] -// pub fn new(val: i32) -> Self { -// TreeNode { -// val, -// left: None, -// right: None -// } -// } -// } -use std::rc::Rc; -use std::cell::RefCell; -impl Solution { - pub fn postorder_traversal(mut root: Option>>) -> Vec { - let mut res = vec![]; - let mut stack = vec![]; - while root.is_some() || !stack.is_empty() { - if root.is_some() { - let next = root.as_mut().unwrap().borrow_mut().left.take(); - stack.push(root); - root = next; - } else { - root = stack.pop().unwrap(); - let next = root.as_mut().unwrap().borrow_mut().right.take(); - if next.is_some() { - stack.push(root); - } else { - res.push(root.as_ref().unwrap().borrow().val); - } - root = next; - } - } - res + const stk: TreeNode[] = [root]; + while (stk.length) { + const { left, right, val } = stk.pop(); + ans.push(val); + left && stk.push(left); + right && stk.push(right); } + ans.reverse(); + return ans; } ``` -### 方法三 +### 方法三:Morris 实现后序遍历 + +Morris 遍历无需使用栈,空间复杂度为 $O(1)$。核心思想是: + +遍历二叉树节点, + +1. 若当前节点 `root` 的右子树为空,将当前节点值添加至结果列表 $ans$ 中,并将当前节点更新为 `root.left` +1. 若当前节点 `root` 的右子树不为空,找到右子树的最左节点 `next`(也即是 `root` 节点在中序遍历下的后继节点): + - 若后继节点 `next` 的左子树为空,将当前节点值添加至结果列表 $ans$ 中,然后将后继节点的左子树指向当前节点 `root`,并将当前节点更新为 `root.right`。 + - 若后继节点 `next` 的左子树不为空,将后继节点左子树指向空(即解除 `next` 与 `root` 的指向关系),并将当前节点更新为 `root.left`。 +1. 循环以上步骤,直至二叉树节点为空,遍历结束。 +1. 最后返回结果列表的逆序即可。 + +> Morris 后序遍历跟 Morris 前序遍历思路一致,只是将前序的“根左右”变为“根右左”,最后逆序结果即可变成“左右根”。 + +时间复杂度 $O(n)$,其中 $n$ 是二叉树的节点数。空间复杂度 $O(1)$。 @@ -477,6 +509,80 @@ class Solution { } ``` +```cpp +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode() : val(0), left(nullptr), right(nullptr) {} + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} + * }; + */ +class Solution { +public: + vector postorderTraversal(TreeNode* root) { + vector ans; + while (root) { + if (!root->right) { + ans.push_back(root->val); + root = root->left; + } else { + TreeNode* next = root->right; + while (next->left && next->left != root) { + next = next->left; + } + if (next->left != root) { + ans.push_back(root->val); + next->left = root; + root = root->right; + } else { + next->left = nullptr; + root = root->left; + } + } + } + reverse(ans.begin(), ans.end()); + return ans; + } +}; +``` + +```go +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func postorderTraversal(root *TreeNode) (ans []int) { + for root != nil { + if root.Right == nil { + ans = append([]int{root.Val}, ans...) + root = root.Left + } else { + next := root.Right + for next.Left != nil && next.Left != root { + next = next.Left + } + if next.Left == nil { + ans = append([]int{root.Val}, ans...) + next.Left = root + root = root.Right + } else { + next.Left = nil + root = root.Left + } + } + } + return +} +``` + ```ts /** * Definition for a binary tree node. @@ -493,19 +599,19 @@ class Solution { */ function postorderTraversal(root: TreeNode | null): number[] { - const res = []; - while (root != null) { + const ans: number[] = []; + while (root !== null) { const { val, left, right } = root; - if (right == null) { - res.push(val); + if (right === null) { + ans.push(val); root = left; } else { let next = right; - while (next.left != null && next.left != root) { + while (next.left !== null && next.left !== root) { next = next.left; } - if (next.left == null) { - res.push(val); + if (next.left === null) { + ans.push(val); next.left = root; root = right; } else { @@ -514,7 +620,7 @@ function postorderTraversal(root: TreeNode | null): number[] { } } } - return res.reverse(); + return ans.reverse(); } ``` diff --git a/solution/0100-0199/0145.Binary Tree Postorder Traversal/README_EN.md b/solution/0100-0199/0145.Binary Tree Postorder Traversal/README_EN.md index 55f196c227478..069a7f19ab0fc 100644 --- a/solution/0100-0199/0145.Binary Tree Postorder Traversal/README_EN.md +++ b/solution/0100-0199/0145.Binary Tree Postorder Traversal/README_EN.md @@ -41,7 +41,11 @@ ## Solutions -### Solution 1 +### Solution 1: Recursion + +We first recursively traverse the left and right subtrees, then visit 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. The space complexity mainly depends on the stack space used for recursive calls. @@ -59,7 +63,6 @@ class Solution: return dfs(root.left) dfs(root.right) - nonlocal ans ans.append(root.val) ans = [] @@ -84,10 +87,9 @@ class Solution: * } */ class Solution { - private List ans; + private List ans = new ArrayList<>(); public List postorderTraversal(TreeNode root) { - ans = new ArrayList<>(); dfs(root); return ans; } @@ -119,26 +121,15 @@ class Solution { public: vector postorderTraversal(TreeNode* root) { vector ans; - while (root) { - if (!root->right) { - ans.push_back(root->val); - root = root->left; - } else { - TreeNode* next = root->right; - while (next->left && next->left != root) { - next = next->left; - } - if (!next->left) { - ans.push_back(root->val); - next->left = root; - root = root->right; - } else { - next->left = nullptr; - root = root->left; - } + function dfs = [&](TreeNode* root) { + if (!root) { + return; } - } - reverse(ans.begin(), ans.end()); + dfs(root->left); + dfs(root->right); + ans.push_back(root->val); + }; + dfs(root); return ans; } }; @@ -153,28 +144,18 @@ public: * Right *TreeNode * } */ -func postorderTraversal(root *TreeNode) []int { - var ans []int - for root != nil { - if root.Right == nil { - ans = append([]int{root.Val}, ans...) - root = root.Left - } else { - next := root.Right - for next.Left != nil && next.Left != root { - next = next.Left - } - if next.Left == nil { - ans = append([]int{root.Val}, ans...) - next.Left = root - root = root.Right - } else { - next.Left = nil - root = root.Left - } +func postorderTraversal(root *TreeNode) (ans []int) { + var dfs func(*TreeNode) + dfs = func(root *TreeNode) { + if root == nil { + return } + dfs(root.Left) + dfs(root.Right) + ans = append(ans, root.Val) } - return ans + dfs(root) + return } ``` @@ -194,25 +175,16 @@ func postorderTraversal(root *TreeNode) []int { */ function postorderTraversal(root: TreeNode | null): number[] { - if (root == null) return []; - let stack = []; - let ans = []; - let prev = null; - while (root || stack.length) { - while (root) { - stack.push(root); - root = root.left; - } - root = stack.pop(); - if (!root.right || root.right == prev) { - ans.push(root.val); - prev = root; - root = null; - } else { - stack.push(root); - root = root.right; + const ans: number[] = []; + const dfs = (root: TreeNode | null) => { + if (!root) { + return; } - } + dfs(root.left); + dfs(root.right); + ans.push(root.val); + }; + dfs(root); return ans; } ``` @@ -239,27 +211,40 @@ function postorderTraversal(root: TreeNode | null): number[] { use std::rc::Rc; use std::cell::RefCell; impl Solution { - fn dfs(root: &Option>>, res: &mut Vec) { + fn dfs(root: &Option>>, ans: &mut Vec) { if root.is_none() { return; } let node = root.as_ref().unwrap().borrow(); - Self::dfs(&node.left, res); - Self::dfs(&node.right, res); - res.push(node.val); + Self::dfs(&node.left, ans); + Self::dfs(&node.right, ans); + ans.push(node.val); } pub fn postorder_traversal(root: Option>>) -> Vec { - let mut res = vec![]; - Self::dfs(&root, &mut res); - res + let mut ans = vec![]; + Self::dfs(&root, &mut ans); + ans } } ``` -### Solution 2 +### Solution 2: Stack Implementation for Postorder Traversal + +The order of preorder traversal is: root, left, right. If we change the order of the left and right children, the order becomes: root, right, left. Finally, reversing the result gives us the postorder traversal result. + +Therefore, the idea of using a stack to implement non-recursive traversal is as follows: + +1. Define a stack $stk$, and first push the root node into the stack. +2. If the stack is not empty, pop a node from the stack each time. +3. Process the node. +4. First push the left child of the node into the stack, then push the right child of the node into the stack (if there are child nodes). +5. Repeat steps 2-4. +6. Reverse the result to get the postorder traversal result. + +The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the number of nodes in the binary tree. The space complexity mainly depends on the stack space. @@ -325,6 +310,76 @@ class Solution { } ``` +```cpp +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode() : val(0), left(nullptr), right(nullptr) {} + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} + * }; + */ +class Solution { +public: + vector postorderTraversal(TreeNode* root) { + vector ans; + if (!root) { + return ans; + } + stack stk; + stk.push(root); + while (stk.size()) { + auto node = stk.top(); + stk.pop(); + ans.push_back(node->val); + if (node->left) { + stk.push(node->left); + } + if (node->right) { + stk.push(node->right); + } + } + reverse(ans.begin(), ans.end()); + return ans; + } +}; +``` + +```go +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func postorderTraversal(root *TreeNode) (ans []int) { + if root == nil { + return + } + stk := []*TreeNode{root} + for len(stk) > 0 { + node := stk[len(stk)-1] + stk = stk[:len(stk)-1] + ans = append(ans, node.Val) + if node.Left != nil { + stk = append(stk, node.Left) + } + if node.Right != nil { + stk = append(stk, node.Right) + } + } + for i, j := 0, len(ans)-1; i < j; i, j = i+1, j-1 { + ans[i], ans[j] = ans[j], ans[i] + } + return +} +``` + ```ts /** * Definition for a binary tree node. @@ -341,63 +396,40 @@ class Solution { */ function postorderTraversal(root: TreeNode | null): number[] { - if (root == null) { - return []; + const ans: number[] = []; + if (!root) { + return ans; } - const { val, left, right } = root; - return [...postorderTraversal(left), ...postorderTraversal(right), val]; -} -``` - -```rust -// Definition for a binary tree node. -// #[derive(Debug, PartialEq, Eq)] -// pub struct TreeNode { -// pub val: i32, -// pub left: Option>>, -// pub right: Option>>, -// } -// -// impl TreeNode { -// #[inline] -// pub fn new(val: i32) -> Self { -// TreeNode { -// val, -// left: None, -// right: None -// } -// } -// } -use std::rc::Rc; -use std::cell::RefCell; -impl Solution { - pub fn postorder_traversal(mut root: Option>>) -> Vec { - let mut res = vec![]; - let mut stack = vec![]; - while root.is_some() || !stack.is_empty() { - if root.is_some() { - let next = root.as_mut().unwrap().borrow_mut().left.take(); - stack.push(root); - root = next; - } else { - root = stack.pop().unwrap(); - let next = root.as_mut().unwrap().borrow_mut().right.take(); - if next.is_some() { - stack.push(root); - } else { - res.push(root.as_ref().unwrap().borrow().val); - } - root = next; - } - } - res + const stk: TreeNode[] = [root]; + while (stk.length) { + const { left, right, val } = stk.pop(); + ans.push(val); + left && stk.push(left); + right && stk.push(right); } + ans.reverse(); + return ans; } ``` -### Solution 3 +### Solution 3: Morris Implementation for Postorder Traversal + +Morris traversal does not require a stack, and its space complexity is $O(1)$. The core idea is: + +Traverse the binary tree nodes, + +1. If the right subtree of the current node `root` is empty, add the current node value to the result list $ans$, and update the current node to `root.left`. +1. If the right subtree of the current node `root` is not empty, find the leftmost node `next` of the right subtree (which is the successor of the `root` node in inorder traversal): + - If the left subtree of the successor node `next` is empty, add the current node value to the result list $ans$, then point the left subtree of the successor node to the current node `root`, and update the current node to `root.right`. + - If the left subtree of the successor node `next` is not empty, point the left subtree of the successor node to null (i.e., disconnect `next` and `root`), and update the current node to `root.left`. +1. Repeat the above steps until the binary tree node is null, and the traversal ends. +1. Finally, return the reverse of the result list. + +> The idea of Morris postorder traversal is consistent with Morris preorder traversal, just change the "root-left-right" of preorder to "root-right-left", and finally reverse the result to become "left-right-root". + +The time complexity is $O(n)$, where $n$ is the number of nodes in the binary tree. The space complexity is $O(1)$. @@ -472,6 +504,80 @@ class Solution { } ``` +```cpp +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode() : val(0), left(nullptr), right(nullptr) {} + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} + * }; + */ +class Solution { +public: + vector postorderTraversal(TreeNode* root) { + vector ans; + while (root) { + if (!root->right) { + ans.push_back(root->val); + root = root->left; + } else { + TreeNode* next = root->right; + while (next->left && next->left != root) { + next = next->left; + } + if (next->left != root) { + ans.push_back(root->val); + next->left = root; + root = root->right; + } else { + next->left = nullptr; + root = root->left; + } + } + } + reverse(ans.begin(), ans.end()); + return ans; + } +}; +``` + +```go +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func postorderTraversal(root *TreeNode) (ans []int) { + for root != nil { + if root.Right == nil { + ans = append([]int{root.Val}, ans...) + root = root.Left + } else { + next := root.Right + for next.Left != nil && next.Left != root { + next = next.Left + } + if next.Left == nil { + ans = append([]int{root.Val}, ans...) + next.Left = root + root = root.Right + } else { + next.Left = nil + root = root.Left + } + } + } + return +} +``` + ```ts /** * Definition for a binary tree node. @@ -488,19 +594,19 @@ class Solution { */ function postorderTraversal(root: TreeNode | null): number[] { - const res = []; - while (root != null) { + const ans: number[] = []; + while (root !== null) { const { val, left, right } = root; - if (right == null) { - res.push(val); + if (right === null) { + ans.push(val); root = left; } else { let next = right; - while (next.left != null && next.left != root) { + while (next.left !== null && next.left !== root) { next = next.left; } - if (next.left == null) { - res.push(val); + if (next.left === null) { + ans.push(val); next.left = root; root = right; } else { @@ -509,7 +615,7 @@ function postorderTraversal(root: TreeNode | null): number[] { } } } - return res.reverse(); + return ans.reverse(); } ``` diff --git a/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution.cpp b/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution.cpp index 005e32dd17533..910d9ae65dd73 100644 --- a/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution.cpp +++ b/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution.cpp @@ -13,26 +13,15 @@ class Solution { public: vector postorderTraversal(TreeNode* root) { vector ans; - while (root) { - if (!root->right) { - ans.push_back(root->val); - root = root->left; - } else { - TreeNode* next = root->right; - while (next->left && next->left != root) { - next = next->left; - } - if (!next->left) { - ans.push_back(root->val); - next->left = root; - root = root->right; - } else { - next->left = nullptr; - root = root->left; - } + function dfs = [&](TreeNode* root) { + if (!root) { + return; } - } - reverse(ans.begin(), ans.end()); + dfs(root->left); + dfs(root->right); + ans.push_back(root->val); + }; + dfs(root); return ans; } }; \ No newline at end of file diff --git a/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution.go b/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution.go index f04a15cf18df2..4fa943a1b3fd3 100644 --- a/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution.go +++ b/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution.go @@ -6,26 +6,16 @@ * Right *TreeNode * } */ -func postorderTraversal(root *TreeNode) []int { - var ans []int - for root != nil { - if root.Right == nil { - ans = append([]int{root.Val}, ans...) - root = root.Left - } else { - next := root.Right - for next.Left != nil && next.Left != root { - next = next.Left - } - if next.Left == nil { - ans = append([]int{root.Val}, ans...) - next.Left = root - root = root.Right - } else { - next.Left = nil - root = root.Left - } +func postorderTraversal(root *TreeNode) (ans []int) { + var dfs func(*TreeNode) + dfs = func(root *TreeNode) { + if root == nil { + return } + dfs(root.Left) + dfs(root.Right) + ans = append(ans, root.Val) } - return ans + dfs(root) + return } \ No newline at end of file diff --git a/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution.java b/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution.java index 3ea04e251f96c..bbbc5e1bec676 100644 --- a/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution.java +++ b/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution.java @@ -14,10 +14,9 @@ * } */ class Solution { - private List ans; + private List ans = new ArrayList<>(); public List postorderTraversal(TreeNode root) { - ans = new ArrayList<>(); dfs(root); return ans; } diff --git a/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution.py b/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution.py index fd82c36dd68b1..7924fa08e3f29 100644 --- a/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution.py +++ b/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution.py @@ -11,7 +11,6 @@ def dfs(root): return dfs(root.left) dfs(root.right) - nonlocal ans ans.append(root.val) ans = [] diff --git a/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution.rs b/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution.rs index 36a4e95075117..c8500d43e8507 100644 --- a/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution.rs +++ b/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution.rs @@ -19,19 +19,19 @@ use std::rc::Rc; use std::cell::RefCell; impl Solution { - fn dfs(root: &Option>>, res: &mut Vec) { + fn dfs(root: &Option>>, ans: &mut Vec) { if root.is_none() { return; } let node = root.as_ref().unwrap().borrow(); - Self::dfs(&node.left, res); - Self::dfs(&node.right, res); - res.push(node.val); + Self::dfs(&node.left, ans); + Self::dfs(&node.right, ans); + ans.push(node.val); } pub fn postorder_traversal(root: Option>>) -> Vec { - let mut res = vec![]; - Self::dfs(&root, &mut res); - res + let mut ans = vec![]; + Self::dfs(&root, &mut ans); + ans } } diff --git a/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution.ts b/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution.ts index 2a86ecdd549d0..f9552c916cc4f 100644 --- a/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution.ts +++ b/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution.ts @@ -13,24 +13,15 @@ */ function postorderTraversal(root: TreeNode | null): number[] { - if (root == null) return []; - let stack = []; - let ans = []; - let prev = null; - while (root || stack.length) { - while (root) { - stack.push(root); - root = root.left; + const ans: number[] = []; + const dfs = (root: TreeNode | null) => { + if (!root) { + return; } - root = stack.pop(); - if (!root.right || root.right == prev) { - ans.push(root.val); - prev = root; - root = null; - } else { - stack.push(root); - root = root.right; - } - } + dfs(root.left); + dfs(root.right); + ans.push(root.val); + }; + dfs(root); return ans; } diff --git a/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution2.cpp b/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution2.cpp new file mode 100644 index 0000000000000..a7d3ca1a2cbd0 --- /dev/null +++ b/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution2.cpp @@ -0,0 +1,35 @@ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode() : val(0), left(nullptr), right(nullptr) {} + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} + * }; + */ +class Solution { +public: + vector postorderTraversal(TreeNode* root) { + vector ans; + if (!root) { + return ans; + } + stack stk; + stk.push(root); + while (stk.size()) { + auto node = stk.top(); + stk.pop(); + ans.push_back(node->val); + if (node->left) { + stk.push(node->left); + } + if (node->right) { + stk.push(node->right); + } + } + reverse(ans.begin(), ans.end()); + return ans; + } +}; \ No newline at end of file diff --git a/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution2.go b/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution2.go new file mode 100644 index 0000000000000..c4b8ee81c948a --- /dev/null +++ b/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution2.go @@ -0,0 +1,29 @@ +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func postorderTraversal(root *TreeNode) (ans []int) { + if root == nil { + return + } + stk := []*TreeNode{root} + for len(stk) > 0 { + node := stk[len(stk)-1] + stk = stk[:len(stk)-1] + ans = append(ans, node.Val) + if node.Left != nil { + stk = append(stk, node.Left) + } + if node.Right != nil { + stk = append(stk, node.Right) + } + } + for i, j := 0, len(ans)-1; i < j; i, j = i+1, j-1 { + ans[i], ans[j] = ans[j], ans[i] + } + return +} \ No newline at end of file diff --git a/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution2.rs b/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution2.rs deleted file mode 100644 index 1b126a82165ac..0000000000000 --- a/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution2.rs +++ /dev/null @@ -1,43 +0,0 @@ -// Definition for a binary tree node. -// #[derive(Debug, PartialEq, Eq)] -// pub struct TreeNode { -// pub val: i32, -// pub left: Option>>, -// pub right: Option>>, -// } -// -// impl TreeNode { -// #[inline] -// pub fn new(val: i32) -> Self { -// TreeNode { -// val, -// left: None, -// right: None -// } -// } -// } -use std::rc::Rc; -use std::cell::RefCell; -impl Solution { - pub fn postorder_traversal(mut root: Option>>) -> Vec { - let mut res = vec![]; - let mut stack = vec![]; - while root.is_some() || !stack.is_empty() { - if root.is_some() { - let next = root.as_mut().unwrap().borrow_mut().left.take(); - stack.push(root); - root = next; - } else { - root = stack.pop().unwrap(); - let next = root.as_mut().unwrap().borrow_mut().right.take(); - if next.is_some() { - stack.push(root); - } else { - res.push(root.as_ref().unwrap().borrow().val); - } - root = next; - } - } - res - } -} diff --git a/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution2.ts b/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution2.ts index e86e8aa1c12aa..236087fd28a53 100644 --- a/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution2.ts +++ b/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution2.ts @@ -13,9 +13,17 @@ */ function postorderTraversal(root: TreeNode | null): number[] { - if (root == null) { - return []; + const ans: number[] = []; + if (!root) { + return ans; } - const { val, left, right } = root; - return [...postorderTraversal(left), ...postorderTraversal(right), val]; + const stk: TreeNode[] = [root]; + while (stk.length) { + const { left, right, val } = stk.pop(); + ans.push(val); + left && stk.push(left); + right && stk.push(right); + } + ans.reverse(); + return ans; } diff --git a/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution3.cpp b/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution3.cpp new file mode 100644 index 0000000000000..b5abf0d997edc --- /dev/null +++ b/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution3.cpp @@ -0,0 +1,38 @@ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode() : val(0), left(nullptr), right(nullptr) {} + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} + * }; + */ +class Solution { +public: + vector postorderTraversal(TreeNode* root) { + vector ans; + while (root) { + if (!root->right) { + ans.push_back(root->val); + root = root->left; + } else { + TreeNode* next = root->right; + while (next->left && next->left != root) { + next = next->left; + } + if (next->left != root) { + ans.push_back(root->val); + next->left = root; + root = root->right; + } else { + next->left = nullptr; + root = root->left; + } + } + } + reverse(ans.begin(), ans.end()); + return ans; + } +}; \ No newline at end of file diff --git a/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution3.go b/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution3.go new file mode 100644 index 0000000000000..4b1a2cf89788d --- /dev/null +++ b/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution3.go @@ -0,0 +1,30 @@ +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func postorderTraversal(root *TreeNode) (ans []int) { + for root != nil { + if root.Right == nil { + ans = append([]int{root.Val}, ans...) + root = root.Left + } else { + next := root.Right + for next.Left != nil && next.Left != root { + next = next.Left + } + if next.Left == nil { + ans = append([]int{root.Val}, ans...) + next.Left = root + root = root.Right + } else { + next.Left = nil + root = root.Left + } + } + } + return +} \ No newline at end of file diff --git a/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution3.ts b/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution3.ts index 6712beeed285f..b6fc95cbdadba 100644 --- a/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution3.ts +++ b/solution/0100-0199/0145.Binary Tree Postorder Traversal/Solution3.ts @@ -13,19 +13,19 @@ */ function postorderTraversal(root: TreeNode | null): number[] { - const res = []; - while (root != null) { + const ans: number[] = []; + while (root !== null) { const { val, left, right } = root; - if (right == null) { - res.push(val); + if (right === null) { + ans.push(val); root = left; } else { let next = right; - while (next.left != null && next.left != root) { + while (next.left !== null && next.left !== root) { next = next.left; } - if (next.left == null) { - res.push(val); + if (next.left === null) { + ans.push(val); next.left = root; root = right; } else { @@ -34,5 +34,5 @@ function postorderTraversal(root: TreeNode | null): number[] { } } } - return res.reverse(); + return ans.reverse(); }