给定一个二叉树,返回它的 后序 遍历。
示例:
输入: [1,null,2,3]
1
\
2
/
3
输出: [3,2,1]
进阶: 递归算法很简单,你可以通过迭代算法完成吗?
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/binary-tree-postorder-traversal
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
详解:
这道题和我的上两篇二叉树的前序遍历,二叉树的中序遍历很像,遍历思想是一样的,关键是什么时候输出结果。
- 首先new一个列表(存储结果),new一个栈, 定义一个当前待处理的节点(初始值为root节点)
- 判断当前节点是否为空,为空退出循环,不为空执行第3步。因为是后序遍历,所以当前节点也不能直接输入到结果(和前序不一样的地方
- 判断左子节点,不为空,压栈,更新当前节点,执行第2步
- 判断右子节点,不为空,压栈,更新当前节点,执行第2步。
- 这一步分析比较长,写成一段(这一步遍历思想和中序的很像,直接拷贝过来,改一下细节):
-
如果执行到了这里,说明当前节点的左右子节点都是空的,但当前节点还没有输出到结果,且还没有压栈,直接将当前节点输出到结果。(这个时候已经就没有压栈的必要了,因为没有子节点,也已经输出了结果)。这个时候就要考虑他的父节点了,父节点在哪呢?栈里!可以看到上面先执行第三步,那么每一个父节点如果他有左节点,那么他的右节点就没有遍历处理(因为随着循环去处理他的左节点了)。所以现在要依次考虑每一个父节点右子节点(此时不需要考虑父节点的左子节点,不理解的自己去面壁思考)
既然依次考虑,所以需要一个循环,如果当前栈顶节点的右子节点不为空,且右子节点不等于当前节点(这个且非常重要,不然就可能会重复处理右子节点),说明当前右子节点还没有处理,更新当前节点,退出循环,执行第2步。否则直接出栈当前节点,且输出当前节点(因为此时说明已经处理完他的左右子节点),接着判断下一个栈顶,直到栈空了
- 至此结束
再详细的思路也不及代码片行,那直接贴代码:
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
if(root == null){
return list;
}
Stack<TreeNode> stack = new Stack<>();
TreeNode tmp = root;
while (tmp != null){
if(tmp.left != null){
stack.push(tmp);
tmp = tmp.left;
continue;
}
if(tmp.right != null){
stack.push(tmp);
tmp = tmp.right;
continue;
}
list.add(tmp.val);
while (true){
if(stack.isEmpty()){
tmp = null;
break;
}
TreeNode peek = stack.peek();
if(peek.right != null && peek.right != tmp){
tmp = peek.right;
break;
}
tmp = stack.pop();
list.add(tmp.val);
}
}
return list;
}
最后贴效率: