LeetCode——二叉树的后序遍历
么事就来刷一刷!
方法:
-
递归
-
非递归
- 模仿系统栈
- 二次翻转法
递归写法
先中后一个鬼样子。
上代码:
/**
* 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<>();
postorder(root,res);
return res;
}
public void postorder(TreeNode root,List<Integer> res){
if(root == null) return;
postorder(root.left,res);
postorder(root.right,res);
res.add(root.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<>();
Stack<TreeNode> stack = new Stack<>();//用来做先序遍历
if(root == null) return res;
TreeNode node = root;
TreeNode prev = root; //用来判断当前子树的右孩子是否已经被访问过了
while(!stack.isEmpty() || node != null){
//找到最左边节点
while(node!=null){
stack.push(node);
node = node.left;
}
node = stack.pop();//回到上一层
//如果右孩子是空,或者被访问过了,则可以访问当前节点
if(node.right == null || prev == node.right){
res.add(node.val);
prev = node;
node = null; //这一步很重要,要不就错误迭代下去了,相当于递归中的顺序结束
}else{
//如果不是,把当前节点压栈,进入右子树遍历
stack.push(node);
node = node.right;
}
}
return res;
}
}
二次翻转法
类似于英语单词的翻转
String s1 = "I Love You"; //原始串
String s3 = "I evoL ouY"; //一次翻转,单词内部翻转————相当于左右子树翻转
String s2 = "You Love I"; //二次翻转,全局翻转 ——————相当于结果序列翻转
思想:后序遍历,其实是交换左右子树的先序遍历,然后再逆序。
或者说,后序遍历逆过来,其实是镜像树的先序遍历。(镜像树即交换左右子树)
因此,需要两个栈,一个栈用来求镜像树先序遍历,把结果放在第二个栈中,第二个栈负责把求得的镜像树先序遍历给逆过来,即为原始树的后序遍历。
代码:
/**
* 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<>();
Stack<TreeNode> stack1 = new Stack<>();//用来做先序遍历
Stack<TreeNode> stack2 = new Stack<>();//用来做结果的逆序
if(root == null) return res;
TreeNode node;//工具人
stack1.push(root);
//先求先序遍历(交换左右子树的遍历,即左子树先入栈,右子树后入栈)
while(!stack1.isEmpty()){
//出栈放入第二个栈
node = stack1.pop();
stack2.push(node);
if(node.left!=null)
stack1.push(node.left);
if(node.right!=null)
stack1.push(node.right);
}
//把镜像树的先序遍历给逆过来
while(!stack2.isEmpty()){
res.add(stack2.pop().val);
}
return res;
}
还是递归好写啊!!!