Poison

145. Binary Tree Postorder Traversal

Recursion
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
// left, right, root

List<Integer> list = new LinkedList<>();
recur(list, root);
return list;
}

private void recur(List<Integer> list, TreeNode node) {
if (node == null) {
return;
}

recur(list, node.left);
recur(list, node.right);
list.add(node.val);
}
}
Iterate
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
// left -> right -> root

List<Integer> numList = new ArrayList<>();

Stack<TreeNode> stack = new Stack<>();
TreeNode pre = null;
while (!stack.isEmpty() || root != null) {
while (root != null) {
stack.push(root);
root = root.left;
}

// now: root is null
TreeNode node = stack.pop();
if (node.right != null && node.right != pre) {
// 当前节点的右子树不为空,应该先处理右子树,leafNode.right != pre 是为了避免从右子树回到 root 时再次进入右子树
stack.push(node); // 注意要将 node push 进栈,因为此时我们进入了右子树而未处理 node 节点
root = node.right; // 进入右子树
} else {
numList.add(node.val);
pre = node;
}
}

return numList;
}
}

个人认为后序遍历的迭代解法是比较难的,主要有两点需要考虑,一是进入右子树后回退至当前节点的处理逻辑中,要避免重复进入右子树,所以引入了 pre 变量来记录上一个被添加至列表的节点,二是处理右子树之前需要记得把当前节点重新入栈,避免仅处理了右子树导致当前节点未被添加至列表的情况。

Reference

145. Binary Tree Postorder Traversal