题目
给定一个二叉树,返回它的 后序 遍历。
示例:
输入: [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来标记节点,如果右子节点之前访问过了或者右子节点不存在,那么就把该节点(第三次访问)加入到列表中。