题目
145. 二叉树的后序遍历
分析
上篇文章我们讲了前序遍历,这道题目是后序遍历。
首先要知道二叉树的后序遍历是什么?【左 右 根】
然后利用递归的思想,就可以得到这道题的答案,任何的递归都可以采用 栈 的结构来实现,所以我会写两种方式来解决这道题目。
代码
递归版本
/*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val = val; }* TreeNode(int val, TreeNode left, TreeNode right) {* this.val = val;* this.left = left;* this.right = right;* }* }*/
class Solution {public List<Integer> postorderTraversal(TreeNode root) {List<Integer> res = new ArrayList<>();func(root,res);return res;}void func(TreeNode cur,List<Integer> res) {if(cur == null) return ;// 先遍历左子树func(cur.left,res);// 再遍历右子树func(cur.right,res);// 最后记录根节点res.add(cur.val);}
}
非递归版本
我们先来看上道题目前序遍历我们是怎么实现的。
前序遍历非递归版本思路:需要借助栈这种数据结构,先把根节点入栈,判断栈是否为空,不为空弹出来栈顶元素,栈顶元素不为空,先把右子树加入栈里面,再把左子树加入栈里面,为空继续遍历栈。
后序遍历:【左 右 根】,我们将这个倒过来看就是【根 右 左】,前序我们是【根 左 右】,所以我们可以由前序遍历的非递归版本改动一些代码就可以得到后续遍历的非递归版本。
认真观察上面的推导过程,我们只需要将前序遍历压入栈的时候将左右子树的顺序颠倒,前序是先押入右子树再压入左子树,后序遍历需要先压入左子树在压入右子树,然后就得到了【根 右 左】了,然后再将得到的集合反转,就可以得到【左 右 根】了,代码如下:
/*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val = val; }* TreeNode(int val, TreeNode left, TreeNode right) {* this.val = val;* this.left = left;* this.right = right;* }* }*/
class Solution {public List<Integer> postorderTraversal(TreeNode root) {List<Integer> res = new ArrayList<>();if(root == null) return res;Stack<TreeNode> stack = new Stack<>();stack.add(root);while(!stack.isEmpty()) {TreeNode node = stack.pop();res.add(node.val);if(node.left != null) stack.push(node.left);if(node.right != null) stack.push(node.right);}Collections.reverse(res);return res;}
}