題目
給定一個二叉樹,返回它的 後序 遍歷。
示例:
輸入: [1,null,2,3]
1
\
2
/
3
輸出: [3,2,1]
進階: 遞歸算法很簡單,你可以通過迭代算法完成嗎?
遞歸
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
List<Integer> ans;
public List<Integer> postorderTraversal(TreeNode root) {
ans = new ArrayList<>();
dfs(root);
return ans;
}
public void dfs(TreeNode root) {
if (root == null) return ;
dfs(root.left);
dfs(root.right);
ans.add(root.val);
}
}
迭代1
自己寫的,主要用了一個HashSet
記錄訪問過的節點。遍歷的時候只有當右孩子爲空或者訪問過的時候纔出棧並訪問該節點,同時將其標記爲以訪問。爲什麼強調自己寫的呢?因爲官方題解還是比我的優雅!
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> ans = new ArrayList<>();
LinkedList<TreeNode> stack = new LinkedList<>();
Set<TreeNode> set = new HashSet<>();
if (root == null) return ans;
// 將空值放入set,這樣判斷空值的時候可以直接用set判斷
set.add(null);
TreeNode p = root;
while (p != null) {
stack.add(p);
p = p.left;
}
while (!stack.isEmpty()) {
p = stack.getLast();
// 只有當前節點的右孩子爲空或者以訪問時,才訪問出棧,同時用set記錄
if (set.contains(p.right)) {
stack.pollLast();
ans.add(p.val);
set.add(p);
} else {
// 否則將其右孩子及右孩子最左邊節點入棧
p = p.right;
while (p != null) {
stack.add(p);
p = p.left;
}
}
}
return ans;
}
}
迭代2
官方題解其實就是前序遍歷,只是利用了LinkedList
鏈表的特性,每訪問一個節點使用頭插法插入鏈表,這樣輸出的時候就變成後序了!
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
LinkedList<TreeNode> stack = new LinkedList<>();
LinkedList<Integer> output = new LinkedList<>();
if (root == null) {
return output;
}
stack.add(root);
while (!stack.isEmpty()) {
TreeNode node = stack.pollLast();
output.addFirst(node.val);
if (node.left != null) {
stack.add(node.left);
}
if (node.right != null) {
stack.add(node.right);
}
}
return output;
}
}