题目
给定一个二叉树,返回它的 后序 遍历。
示例:
输入: [1,null,2,3] 1 \ 2 / 3 输出: [3,2,1]
进阶: 递归算法很简单,你可以通过迭代算法完成吗?
解题
方法一:递归
python解法
# Definition for a binary tree node. # class TreeNode: # def __init__(self, val=0, left=None, right=None): # self.val = val # self.left = left # self.right = right class Solution: def postorderTraversal(self, root: TreeNode) -> List[int]: def postorder(root): if not root: return postorder(root.left) postorder(root.right) res.append(root.val) res = [] postorder(root) return res
c++解法
class Solution { public: void postorder(TreeNode* root,vector<int>& res){ if(!root) return; postorder(root->left,res); postorder(root->right,res); res.push_back(root->val); } vector<int> postorderTraversal(TreeNode* root) { vector<int> res; postorder(root,res); return res; } };
方法二:迭代
模板解法:
继续按照上面的思想,这次我们反着思考,节点 cur 先到达最右端的叶子节点并将路径上的节点入栈;
然后每次从栈中弹出一个元素后,cur 到达它的左孩子,并将左孩子看作 cur 继续执行上面的步骤。
最后将结果反向输出即可。参考代码如下:
python解法
# Definition for a binary tree node. # class TreeNode: # def __init__(self, val=0, left=None, right=None): # self.val = val # self.left = left # self.right = right class Solution: def postorderTraversal(self, root: TreeNode) -> List[int]: if not root: return [] cur,stack,res = root,[],[] while cur or stack: while cur: res.append(cur.val) stack.append(cur) cur = cur.right cur = stack.pop() cur = cur.left return res[::-1]
然而,后序遍历采用模板解法并没有按照真实的栈操作,而是利用了结果的特点反向输出,不免显得技术含量不足。
因此掌握标准的栈操作解法是必要的。
c++解法
class Solution { public: vector<int> postorderTraversal(TreeNode* root) { if(!root) return {}; vector<int> res; stack<TreeNode*> stack; TreeNode* cur=root; while(!stack.empty()||cur){ while(cur){ res.push_back(cur->val); stack.push(cur); cur=cur->right; } cur=stack.top(); stack.pop(); cur=cur->left; } reverse(res.begin(),res.end()); return res; } };
java解法
调用Collections里面的reverse
class Solution { public List<Integer> postorderTraversal(TreeNode root) { List<Integer> res=new LinkedList<>(); TreeNode cur=root; Stack<TreeNode> st=new Stack<>(); while(!st.isEmpty()||cur!=null){ while(cur!=null){ res.add(cur.val); st.push(cur); cur=cur.right; } cur=st.pop(); cur=cur.left; } Collections.reverse(res); return res; } }
常规解法:
python解法
# Definition for a binary tree node. # class TreeNode: # def __init__(self, val=0, left=None, right=None): # self.val = val # self.left = left # self.right = right class Solution: def postorderTraversal(self, root: TreeNode) -> List[int]: if not root: return [] stack = [] res = [] cur = root prev = None while stack or cur: while cur: stack.append(cur) cur = cur.left cur = stack.pop() if not cur.right or cur.right==prev: res.append(cur.val) prev = cur cur = None # 防止进入上面的while else: stack.append(cur)# 还是要加入到stack,这样才能回到上面的if 语句中去 cur = cur.right return res
c++解法
class Solution { public: vector<int> postorderTraversal(TreeNode* root) { if(!root) return {}; vector<int> res; stack<TreeNode*> stack; TreeNode* cur=root; TreeNode* prev=nullptr; while(!stack.empty()||cur){ while(cur){ stack.push(cur); cur=cur->left; } cur=stack.top(); stack.pop(); if(!cur->right||cur->right==prev){ res.push_back(cur->val); prev=cur; cur=nullptr; } else{ stack.push(cur); cur=cur->right; } } return res; } };
用prev来标记节点,如果右子节点之前访问过了或者右子节点不存在,那么就把该节点(第三次访问)加入到列表中。