Solution 1
递归思路参考 0094. Binary Tree Inorder Traversal 和 0144. Binary Tree Preorder Traversal
- 时间复杂度: O ( n ) O(n) O(n),其中 n n n为输入树节点的个数,一次遍历
- 空间复杂度: O ( n ) O(n) O(n),其中 n n n为输入树节点的个数,最坏情况下所需要的递归函数调用
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int> ans;
if (root != nullptr) {
this->postorder(root, ans);
}
return ans;
}
private:
void postorder(TreeNode* node, vector<int> & ans) {
if (node->left != nullptr) {
this->postorder(node->left, ans);
}
if (node->right != nullptr) {
this->postorder(node->right, ans);
}
ans.push_back(node->val);
}
};
Solution 2
【部分官方题解】先中间再右后左然后结果反转我能想到并成功实现,但是正序处理的话我自己没能想好节点怎么保存……
正序遍历时候整体还是先左再右最后中间,但是怎么确定中间节点的保存时刻比较讲究。
官方题解的思路就是,在完成左子树处理之后中间节点再次入栈,并用一个额外的指针指示他的右节点。再一次中间节点出栈可以用这个方式判断(这个节点可以在伪递归过程中不断地向上层更新),并保存节点。
- 时间复杂度: O ( n ) O(n) O(n),其中 n n n为输入树节点的个数,一次遍历
- 空间复杂度: O ( n ) O(n) O(n),其中 n n n为输入树节点的个数,最坏情况下的栈占用空间
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int> ans
if (root == nullptr) {
return ans;
}
stack<TreeNode *> S;
auto node = root;
TreeNode *prev = nullptr;
while (node != nullptr || !S.empty()) {
while (node != nullptr) {
// 左子树入栈
S.push(node);
node = node->left;
}
// 开始出栈遍历
node = S.top();
S.pop();
if (node->right == nullptr || node->right == prev) {
// 右子树为空或者右子树遍历完成
ans.push_back(node->val);
prev = node; // 上层中间节点的指示指针位置确定
node = nullptr; // 下一轮强制出栈
} else {
// 右子树入栈
S.push(node);
node = node->right;
}
}
return ans;
}
};
Solution 3
【官方题解】Morris,但是真的好难……
仍然是将整个树的结构调整为中序遍历的结构,但是不删除原有的结构(因为要找原有结构下的左子树和右子树),同时在这个过程中不对遍历结果进行保存。
当对左子树的前去位置遍历发现一个环时,说明两个情况:
- 左子树只有一个节点,可以完成这个子树的遍历
- 左子树在完成左右子树遍历后回到根部,此时,所有次级左子树都遍历完毕,应当只剩一下左子树最右侧的路径没有遍历,按照遍历顺序逆序保存
需要注意最后一层的遍历结束后,整个树的最右侧路径还没有处理,同理进行处理。
这个逻辑时真的比较难处理,也是因为我过去实现的都是直接保存结果删旧链接的形式,很难调整为这个思路。
- 时间复杂度: O ( n ) O(n) O(n),其中 n n n为输入树节点的个数,最多三次遍历
- 空间复杂度: O ( 1 ) O(1) O(1),仅维护常数个状态量
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int> ans;
auto node = root;
while (node != nullptr) {
TreeNode* next = node->left;
// cout << node->val << endl;
// cout << ans[ans.size() - 1] << endl;
if (next != nullptr) {
while (next->right != nullptr && next->right != node) {
next = next->right;
}
if (next->right == nullptr) {
next->right = node;
node = node->left;
continue;
} else {
next->right = nullptr;
this->addNodes(node->left, ans);
}
}
node = node->right;
}
this->addNodes(root, ans);
return ans;
}
private:
void addNodes(TreeNode* node, vector<int> & ans) {
int count = 0;
while (node != nullptr) {
++count;
ans.push_back(node->val);
node = node->right;
}
reverse(ans.end() - count, ans.end());
}
};
Solution 4
Solution 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: Optional[TreeNode]) -> List[int]:
def postorder(node: Optional[TreeNode]) -> None:
nonlocal ans
if node.left is not None: postorder(node.left)
if node.right is not None: postorder(node.right)
ans.append(node.val)
ans = []
if root is not None: postorder(root)
return ans
Solution 5
Solution 2的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: Optional[TreeNode]) -> List[int]:
ans = []
stack = []
node = root
prev = None
while node is not None or stack:
# print(node)
while node is not None:
stack.append(node)
node = node.left
# print(stack)
node = stack.pop()
if node.right is None or node.right == prev:
ans.append(node.val)
prev = node
node = None
else:
stack.append(node)
node = node.right
return ans
Solution 6
Solution 3的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: Optional[TreeNode]) -> List[int]:
def postorder(node: Optional[TreeNode]) -> None:
nonlocal ans
if node.left is not None: postorder(node.left)
if node.right is not None: postorder(node.right)
ans.append(node.val)
def addNodes(node: Optional[TreeNode]):
nonlocal ans
count = 0
while node is not None:
count += 1
ans.append(node.val)
node = node.right
if len(ans) - count == 0:
ans = ans [-1::-1]
else:
ans[len(ans) - count:] = ans[:len(ans) - count - 1: -1]
ans = []
node = root
while node is not None:
pre = node.left
if pre is not None:
while pre.right is not None and pre.right != node:
pre = pre.right
# print(node.val, pre.val)
if pre.right is None:
pre.right = node
node = node.left
continue
else:
pre.right = None
addNodes(node.left)
node = node.right
addNodes(root)
return ans