题目
给你一棵二叉树的根节点 root
,返回其节点值的 后序遍历 。
提示:
- 树中节点的数目在范围
[0, 100]
内 -100 <= Node.val <= 100
解法1:递归
二叉树具有天然的递归结构,后序遍历是在访问完节点的左右子树后才对数据进行操作。代码如下:
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int> result{};
result.reserve(100);
postorderTraversal(root, result);
return result;
}
private:
void postorderTraversal(TreeNode* root, vector<int>& result)
{
if (root == nullptr) {
return;
}
postorderTraversal(root->left, result);
postorderTraversal(root->right, result);
result.push_back(root->val);
}
};
时间复杂度为O(n)
,空间复杂度为O(n)
,执行结果如下:
解法2:迭代
由于二叉树具有天然的递归结构,因此递归代码实现较为简单。若采用迭代的方法,需要借助栈进行处理。在后序遍历中,在访问完节点的左右子树后才对数据进行操作。代码如下:
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int> result{};
result.reserve(100); // 由于最多存在100个元素,预先分配充足的空间
stack<TreeNode*> buffer{};
// 在访问完左右节点后,需要针对该节点做特殊处理.
// 当重新从栈中弹出节点时,如果该节点的右孩子和prev相等,那么表示其右孩子已经访问过,无需再访问,避免无限循环
TreeNode* prev = nullptr;
// 如果节点为空且栈缓存非空,需要从栈中弹出一个节点进行处理
while ((root != nullptr) || (!buffer.empty())) {
while (root != nullptr) {
buffer.push(root);
root = root->left;
}
// 访问完左子树后,从栈缓存中弹出一个节点,即当前待访问的节点
root = buffer.top();
buffer.pop();
// 如果右孩子为空或者右孩子等于prev,表示右孩子已经访问过,此时后序遍历处理值
if ((root->right == nullptr) || (root->right == prev)) {
result.push_back(root->val);
prev = root;
root = nullptr;
} else {
buffer.push(root);
root = root->right;
}
}
return result;
}
};
时间复杂度为O(n)
,空间复杂度为O(n)
,执行结果如下: