題目
給定一個二叉樹,返回它的 後序 遍歷。
示例:
輸入: [1,null,2,3]
1
\
2
/
3
輸出: [3,2,1]
進階: 遞歸算法很簡單,你可以通過迭代算法完成嗎?
Related Topics 棧 樹
思路
後序遍歷:左-右-中
題目也說了遞歸很簡單,使用一個DFS(深度優先遍歷),分別按左右中,加到結果列表裏。我相信你也可以寫得出來。
什麼是迭代?
遞歸是使用函數棧去實現的,也就是自己調用自己。每次調用都需要去開闢方法棧空間,當棧太深時就會出現棧溢出。
那麼如何用迭代實現呢?
概念 —— 迭代是重複反饋過程的活動,其目的通常是爲了接近併到達所需的目標或結果。 每一次對過程的重複被稱爲一次迭代
,而每一次迭代得到的結果會被用來作爲下一次迭代的初始值。
說白了,就是能用for
、 while
實現的,就別用遞歸。
一般的能寫成遞歸的都能轉化成迭代
,但迭代寫完後相對於遞歸來說沒有那麼好理解
解法
遞歸
class Solution {
List<Integer> res ;
public List<Integer> postorderTraversal(TreeNode root) {
res = new ArrayList<>();
dfs(root);
return res;
}
public void dfs(TreeNode node) {
if (node == null) return ;
dfs(node.left);
dfs(node.right);
res.add(node.val);
}
}
迭代
1
/ \
2 3
/ \ / \
4 5 6 7
以上面這棵樹爲例子,我們要實現按照左邊-右邊-中間的順序輸出。在這裏用棧就很巧妙,每次都推出一個元素,並將左右子樹分別壓入棧。而推出的這個元素就是根節點,每次拼接到鏈表的頭部。
結合代碼走一遍
1
做爲根節點,壓入棧。
推出1
,將自己的左右節點2
、3
入棧。(按2,3 的順序入棧)
推出3
,將自己的左右節點6
、7
入棧。
推出7
,7
爲葉子節點,無入棧元素
推出6
,6
爲葉子節點,無入棧元素
此時右子樹已經遍歷完。
推出2
,將自己的左右節點4
、5
入棧。(按4,5 的順序入棧)
推出5
,5
爲葉子節點,無入棧元素
推出4
,4
爲葉子節點,無入棧元素
完成!棧裏已無元素。
這裏呢畫個圖就能一下子明白啥回事!
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
LinkedList<Integer> res = new LinkedList<>();
if (root==null) return res;
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode pop = stack.pop();
res.addFirst(pop.val);
if (null!=pop.left) stack.push(pop.left);
if (null!=pop.right) stack.push(pop.right);
}
return res;
}
}