1. 题目
题目描述
求给定的二叉树的后序遍历。
例如:
给定的二叉树为{1,#,2,3},
1↵ ↵ 2↵ /↵ 3↵
返回[3,2,1].
备注;用递归来解这道题太没有新意了,可以给出迭代的解法么?
2. 思路
2.1 递归
我们先考虑一下递归的思路,从三种遍历来看(前序、中序、后序),都是可以通过递归来实现的,只需要不断调用自身函数,但是问题就是带来的空间复杂度太高。因此最好的方案是迭代。
2.2 迭代
如果是前序遍历,我们的顺序是根节点,左节点,右节点。如果我们用一个栈来实现,可以这样考虑:先把根节点压入栈,在栈中有元素的时候循环:每次弹出栈顶元素,然后先压入栈顶元素的右边节点,再压入栈顶元素的左边节点。
因为栈是先进后出,因此要先压入右边的节点,因此第二次执行while循环的时候,栈顶元素就是左节点A,然后再来压入右节点A->R压入左节点A->L,注意,下一次循环的时候,谁是栈顶元素?没错,就是左节点。就是通过这种栈的特性,实现了递归的过程!
所以要能够理解,为什么有人说栈和递归是一样的。
以上过程实现了根、左、右的遍历过程,那我们想想后序遍历:左、右、根的的顺序,可不可以借鉴这个思路?可以的,我们只需要实现根、右、左的过程,再reverse一下,就OK了,是不是很骚,是的。
代码
/**
* Definition for binary tree
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
//思想很牛逼,建议多理解两遍。总结一下前序中序后序遍历的一些方法。以及栈的一些巧妙使用。
class Solution {
public:
vector<int> postorderTraversal(TreeNode *root) {
vector<int> vec;
if (!root)
return vec;
stack<TreeNode*> st;
st.push(root);
//vec.push_back(root->val);
while(st.size()){
auto tmp = st.top();
st.pop();
vec.push_back(tmp->val);
if (tmp->left)
st.push(tmp->left);
if (tmp->right)
st.push(tmp->right);
}
reverse(vec.begin(),vec.end());
return vec;
}
};