mirror of
https://github.com/ShusenTang/LeetCode.git
synced 2024-09-02 14:20:01 +00:00
Create 145. Binary Tree Postorder Traversal.md
This commit is contained in:
parent
e3c5873d3b
commit
6ccf6c02ae
107
solutions/145. Binary Tree Postorder Traversal.md
Normal file
107
solutions/145. Binary Tree Postorder Traversal.md
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
# [145. Binary Tree Postorder Traversal](https://leetcode.com/problems/binary-tree-postorder-traversal/)
|
||||||
|
|
||||||
|
# 思路
|
||||||
|
|
||||||
|
二叉树的后序遍历。递归方式很简单,这里主要讨论非递归方式。
|
||||||
|
|
||||||
|
## 思路一
|
||||||
|
除了层序遍历,二叉树的前序、中序、后序遍历的非递归算法一般都是用栈。后序遍历中比较特殊的是每个节点会有两次出现在栈顶:
|
||||||
|
1. 第一次是当其左右子树都还没访问时,所以应该按序将其右、左子树入栈(注意不会将该结点出栈);
|
||||||
|
2. 第二次是当其左右子树都遍历完毕时,所以应该将其出栈并访问。
|
||||||
|
|
||||||
|
可见我们需要记录一下每个结点是否已经在栈顶出现过一次了,可用hashset来记录。
|
||||||
|
|
||||||
|
## 思路二
|
||||||
|
|
||||||
|
思路一需要一个hashset来记录某个结点的左右子树是否已经访问完毕(即之前是否在栈顶出现过),空间复杂度比较大。
|
||||||
|
|
||||||
|
其实可以用一个指针pre达到上述目的,用pre指向前一个遍历的节点,栈顶元素分如下三种情况:
|
||||||
|
1. 如果栈顶元素是叶子,那么直接出栈并访问然后更新pre;
|
||||||
|
2. 如果栈顶元素的左孩子或右孩子是pre,说明左右子树都已经处理完毕,那么应该将当前元素出栈并访问然后更新pre;
|
||||||
|
3. 否则,说明左右子树还未访问,将左右孩子入栈。
|
||||||
|
|
||||||
|
需要说明的是pre的初始值原则上任意都可以,但是其实不能为NULL,否则如果某结点有一个空孩子,那么就会满足上面的第2个条件,这是不对的。
|
||||||
|
同理也不能初始化为树中其他结点以免错误判断上面的第2个条件(初始为root是可以的)。
|
||||||
|
|
||||||
|
## 思路三、修改前序遍历
|
||||||
|
|
||||||
|
我们知道前序遍历是按照"根左右"的原则遍历的,而后序遍历则是按照"左右根"的遍历原则。那么我们可以稍加修改前序遍历的代码,使其按照"根右左"遍历,最后再将结果翻转就得到了"左右根"遍历结果。
|
||||||
|
|
||||||
|
# C++
|
||||||
|
## 思路一
|
||||||
|
``` C++
|
||||||
|
class Solution {
|
||||||
|
public:
|
||||||
|
vector<int> postorderTraversal(TreeNode* root) {
|
||||||
|
vector<int>res;
|
||||||
|
if(!root) return res;
|
||||||
|
stack<TreeNode *>stk{{root}};
|
||||||
|
set<TreeNode *>flag;
|
||||||
|
TreeNode *p = NULL;
|
||||||
|
while(!stk.empty()){
|
||||||
|
p = stk.top();
|
||||||
|
if(flag.find(p) == flag.end()){ // 第一次出现在栈顶
|
||||||
|
flag.insert(p);
|
||||||
|
if(p -> right) stk.push(p -> right);
|
||||||
|
if(p -> left) stk.push(p -> left);
|
||||||
|
}
|
||||||
|
else{ // 第二次出现在栈顶
|
||||||
|
res.push_back(p -> val);
|
||||||
|
stk.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## 思路二
|
||||||
|
``` C++
|
||||||
|
class Solution {
|
||||||
|
public:
|
||||||
|
vector<int> postorderTraversal(TreeNode* root) {
|
||||||
|
vector<int>res;
|
||||||
|
if(!root) return res;
|
||||||
|
stack<TreeNode *>stk{{root}};
|
||||||
|
TreeNode *p = NULL, *pre = root; // pre不能为NULL!!
|
||||||
|
while(!stk.empty()){
|
||||||
|
p = stk.top();
|
||||||
|
if((!p -> left && !p -> right) || p -> left == pre || p -> right == pre){
|
||||||
|
res.push_back(p -> val);
|
||||||
|
stk.pop();
|
||||||
|
pre = p;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if(p -> right) stk.push(p -> right);
|
||||||
|
if(p -> left) stk.push(p -> left);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## 思路三
|
||||||
|
``` C++
|
||||||
|
class Solution {
|
||||||
|
public:
|
||||||
|
vector<int> postorderTraversal(TreeNode* root) {
|
||||||
|
vector<int>res;
|
||||||
|
if(!root) return res;
|
||||||
|
stack<TreeNode *>stk{{root}};
|
||||||
|
TreeNode *p = NULL;
|
||||||
|
while(!stk.empty()){
|
||||||
|
p = stk.top(); stk.pop();
|
||||||
|
res.push_back(p -> val);
|
||||||
|
// 前序遍历这里是先右后左
|
||||||
|
if(p -> left) stk.push(p -> left);
|
||||||
|
if(p -> right) stk.push(p -> right);
|
||||||
|
}
|
||||||
|
|
||||||
|
reverse(res.begin(), res.end()); // 前序遍历无这句
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user