leetcode题目
binary-tree-postorder-traversal
题目描述
-
Given a binary tree, return the postorder traversal of its nodes’ values.
-
For example:
-
Given binary tree{1,#,2,3},
1
\
2
/
3 -
return[3,2,1].
-
Note: Recursive solution is trivial, could you do it iteratively?
思路
1、递归
2、两个栈倒换元素实现
3、栈、线性表倒换元素后反转线性表
4、单个栈处理,有条件元素出栈
代码
package com.my.test.leetcode.tree;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Stack;
/**
* 题目:
* binary-tree-postorder-traversal
*
* 题目描述:
* Given a binary tree, return the postorder traversal of its nodes' values.
* For example:
* Given binary tree{1,#,2,3},
1
\
2
/
3
* return[3,2,1].
* Note: Recursive solution is trivial, could you do it iteratively?
*
*/
public class PostOrderTree {
static class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
/**
* 递归解法(栈溢出/内存溢出 风险,不推荐)
*/
public ArrayList<Integer> postorderRecursiveTraversal(TreeNode root) {
ArrayList<Integer> retList = new ArrayList<>();
if (root == null) {
return retList;
}
postorderRecursiveTraversal(root, retList);
return retList;
}
private void postorderRecursiveTraversal(TreeNode root, ArrayList<Integer> lst) {
if (root == null) {
return;
}
postorderRecursiveTraversal(root.left, lst);
postorderRecursiveTraversal(root.right, lst);
lst.add(root.val);
}
/**
* 思路:
* 1、使用两个栈来实现后续遍历
* 2、一个栈s1初始化只有头节点,按照左右顺序把孩子节点入栈
* 3、另一个栈s2在s1元素出栈时把元素入栈,入栈顺序为右左,则出栈顺序为左右孩子,最后为中间节点。
*/
public ArrayList<Integer> postorderTraversalByTwoStack(TreeNode root) {
ArrayList<Integer> retList = new ArrayList<>();
if (root == null) {
return retList;
}
// 初始化s1 s2
Stack<TreeNode> s1 = new Stack<>();
s1.push(root);
Stack<TreeNode> s2 = new Stack<>();
TreeNode curNode;
// s1中节点弹出后,压入s2,左右孩子节点依次压入s1
while (!s1.empty()) {
curNode = s1.pop();
s2.push(curNode);
// 依次压入左右孩子,s1弹出元素顺序为右左,s2入栈顺序为右左,保证s2出栈顺序为左右
if (curNode.left != null) {
s1.push(curNode.left);
}
if (curNode.right != null) {
s1.push(curNode.right);
}
}
// s2中元素出栈,转移到retList
while (!s2.empty()) {
retList.add(s2.pop().val);
}
return retList;
}
/**
* 思路(巧妙解法,其实与上述思路类似):
* 1、先序遍历的变体--中右左顺序遍历树,结果入ArrayList
* 2、ArrayList反转
*/
public ArrayList<Integer> postorderTraversalByRightLeftPreOrder(TreeNode root) {
ArrayList<Integer> retList = new ArrayList<>();
if (root == null) {
return retList;
}
// 初始化栈,便于先序遍历(中右左顺序)二叉树
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
TreeNode curNode;
// 先序的变体-中右左遍历,结果保存到retList,然后反转retList
while (!stack.empty()) {
curNode = stack.pop();
retList.add(curNode.val);
// 先左后右添加 保证栈弹出顺序是右左,在反转retList后,整体顺讯为左右中后续遍历
// 添加左孩子
if (curNode.left != null) {
stack.push(curNode.left);
}
// 添加右孩子
if (curNode.right != null) {
stack.push(curNode.right);
}
}
// 反转ArrayList
Collections.reverse(retList);
return retList;
}
/**
* 思路:
* 1、初始一个栈,有根节点元素
* 2、如果元素的左右孩子节点都为空,则出栈;上次出栈的是元素的右孩子,则出栈;上次出栈的是元素的左孩子、并且元素的右孩子为空,则出栈
* 3、不满足出栈条件,则添加右孩子,再添加左孩子
*/
public ArrayList<Integer> postorderTraversal(TreeNode root) {
ArrayList<Integer> retList = new ArrayList<>();
if (root == null) {
return retList;
}
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
TreeNode pre = null;
TreeNode curNode;
while (!stack.empty()) {
curNode = stack.peek();
if (hasNoChilds(curNode) || IsPrePopLeftChildAndNoRightChild(curNode, pre) || IsPrePopRightChild(curNode, pre)) {
// 弹出元素
pre = stack.pop();
retList.add(pre.val);
} else {
// 添加右孩子
if (curNode.right != null) {
stack.push(curNode.right);
}
// 添加左孩子
if (curNode.left != null) {
stack.push(curNode.left);
}
}
}
return retList;
}
private boolean hasNoChilds(TreeNode node) {
return node.left == null && node.right == null;
}
private boolean IsPrePopLeftChildAndNoRightChild(TreeNode root, TreeNode prePop) {
return root.left == prePop && root.right == null;
}
private boolean IsPrePopRightChild(TreeNode root, TreeNode prePop) {
return prePop != null && root.right == prePop;
}
public static void main(String[] args) {
TreeNode root = new TreeNode(1);
TreeNode right = new TreeNode(2);
root.right = right;
TreeNode left = new TreeNode(3);
right.left = left;
System.out.println(new PostOrderTree().postorderRecursiveTraversal(root));
System.out.println(new PostOrderTree().postorderTraversalByTwoStack(root));
System.out.println(new PostOrderTree().postorderTraversalByRightLeftPreOrder(root));
System.out.println(new PostOrderTree().postorderTraversal(root));
TreeNode root1 = new TreeNode(3);
TreeNode left1 = new TreeNode(1);
root1.left = left1;
TreeNode right1 = new TreeNode(2);
root1.right = right1;
System.out.println(new PostOrderTree().postorderRecursiveTraversal(root1));
System.out.println(new PostOrderTree().postorderTraversalByTwoStack(root1));
System.out.println(new PostOrderTree().postorderTraversalByRightLeftPreOrder(root1));
System.out.println(new PostOrderTree().postorderTraversal(root1));
}
}