用栈是正常的思路,但难点在于不要刻意去破坏树的原有结构,所以要用一个prePopedNode来记录上一个被弹栈的节点(由于是后续遍历【压栈顺序是父>右>左】上一个被弹的一定是当前节点的子节点或者左侧节点)
import java.util.*;
/*
* public class TreeNode {
* int val = 0;
* TreeNode left = null;
* TreeNode right = null;
* }
*/
public class Solution {
/**
*
* @param root TreeNode类
* @return int整型ArrayList
*/
public ArrayList<Integer> postorderTraversal (TreeNode root) {
// write code here
ArrayList<Integer> res = new ArrayList<>();
if (root == null) {
return res;
}
Stack<TreeNode> stk = new Stack<>();
stk.push(root);
// 表示之前没有任何节点被弹过
TreeNode prePopedNode = null;
while (!stk.empty()) {
TreeNode node = stk.peek();
if (shouldPop(node, prePopedNode)) {
res.add(node.val);
stk.pop();
prePopedNode = node;
continue;
}
if (node.right != null) {
stk.push(node.right);
}
if (node.left != null) {
stk.push(node.left);
}
}
return res;
}
private boolean shouldPop(TreeNode node, TreeNode prePopedNode) {
// 叶子节点,必弹
if (node.left == null && node.right == null) {
return true;
}
// 之前弹过
if (prePopedNode != null) {
// 之前弹的是其子节点,由于是后续遍历,所以其子节点已经被弹完了,他也必须得弹调
if (node.left == prePopedNode || node.right == prePopedNode) {
return true;
}
// 之前弹的不是其子节点,所以其子节点还未压栈过,继续压(遍历其子节点)
else {
return false;
}
}
return false;
}
} 


京公网安备 11010502036488号