145 二叉树的后序遍历
给你一棵二叉树的根节点 root ,返回其节点值的 后序遍历 。
示例 1:
输入:root = [1,null,2,3]
输出:[3,2,1]
示例 2:
输入:root = []
输出:[]
示例 3:
输入:root = [1]
输出:[1]
提示:
树中节点的数目在范围 [0, 100] 内
-100 <= Node.val <= 100
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/binary-tree-postorder-traversal
解决方案:
提供思路
1)二叉树的后序遍历的方法为:依次遍历左子树、右子树和根结点,对于左子树和右子树使用同样的方法遍历。由于遍历过程具有递归的性质,因此可以使用递归的方法实现二叉树的后序遍历。
递归的终止条件是当前结点为空。对于非终止条件,递归的做法如下。
1.对当前结点的左子树调用递归。
2.对当前结点的右子树调用递归。
3.将当前结点的结点值加入后序遍历序列。
遍历结束之后即可得到后序遍历序列。
2)使用迭代的方法实现二叉树的后序遍历,则需要使用栈存储结点。
相比于前序遍历和中序遍历,后序遍历的迭代较为复杂。由于后序遍历对于每个子树都是最后访问根结点,因此需要记录上一个访问的结点,才能确保不会重复访问同一个结点。
从根结点开始遍历,遍历的终止条件是栈为空且当前结点为空。遍历的做法如下。
如果当前结点不为空,则将当前结点入栈,然后将当前结点移动到其左子结点,重复该操作直到当前结点为空。
将当前结点设为栈顶结点,判断其右子结点是否为空以及是否为上一个访问的结点。
1.如果当前结点的右子结点不为空且不为上一个访问的结点,则将当前结点移动到其右子结点。
2.如果当前结点的右子结点为空或者为上一个访问的结点,则将当前结点出栈,将当前结点的结点值加入后序遍历序列,将上一个访问的结点设为当前结点,将当前结点设为空。
3.重复上述操作,直到达到遍历的终止条件。
3)莫里斯遍历是使用常数空间遍历二叉树的方法,由 J. H. Morris 提出。莫里斯遍历的核心思想是利用二叉树的空闲指针维护遍历顺序,达到省略栈空间的目的。
相比于前序遍历和中序遍历,后序遍历的莫里斯遍历较为复杂。
从根结点开始遍历,遍历的终止条件是当前结点为空。
1.对于每个结点,判断当前结点的左子树是否为空,执行相应的操作。
如果当前结点的左子树为空,则将当前结点移动到其右子结点。
如果当前结点的左子树不为空,则找到当前结点的前驱结点,前驱结点为当前结点的左子树中的最右边的结点,判断前驱结点的右子结点是否为空。
如果前驱结点的右子结点为空,则将前驱结点的右子结点设为当前结点,将当前结点移动到其左子结点。
如果前驱结点的右子结点不为空,则将前驱结点的右子结点设为空,将当前结点的左子结点至当前结点的前驱结点的路径上的所有结点的结点值倒序加入后序遍历序列,将当前结点移动到其右子结点。
2.重复上述操作,直到达到遍历的终止条件。最后将根结点的结点值加入后序遍历序列。
上代码:
//1
public class Solution
{
IList<int> traversal = new List<int>();
public IList<int> PostorderTraversal(TreeNode root)
{
Postorder(root);
return traversal;
}
public void Postorder(TreeNode node)
{
if (node == null)
{
return;
}
Postorder(node.left);
Postorder(node.right);
traversal.Add(node.val);
}
}
//2
public class Solution
{
public IList<int> PostorderTraversal(TreeNode root)
{
IList<int> traversal = new List<int>();
Stack<TreeNode> stack = new Stack<TreeNode>();
TreeNode node = root, prev = null;
while (stack.Count > 0 || node != null)
{
while (node != null)
{
stack.Push(node);
node = node.left;
}
node = stack.Peek();
if (node.right != null && node.right != prev)
{
node = node.right;
}
else
{
stack.Pop();
traversal.Add(node.val);
prev = node;
node = null;
}
}
return traversal;
}
}
//3
public class Solution
{
public IList<int> PostorderTraversal(TreeNode root)
{
IList<int> traversal = new List<int>();
TreeNode node = root;
while (node != null)
{
if (node.left == null)
{
node = node.right;
}
else
{
TreeNode predecessor = node.left;
while (predecessor.right != null && predecessor.right != node)
{
predecessor = predecessor.right;
}
if (predecessor.right == null)
{
predecessor.right = node;
node = node.left;
}
else
{
predecessor.right = null;
AddToTraversal(node.left, traversal);
node = node.right;
}
}
}
AddToTraversal(root, traversal);
return traversal;
}
public void AddToTraversal(TreeNode node, IList<int> traversal)
{
int size1 = traversal.Count;
while (node != null)
{
traversal.Add(node.val);
node = node.right;
}
int size2 = traversal.Count;
int left = size1, right = size2 - 1;
while (left < right)
{
int val1 = traversal[left], val2 = traversal[right];
traversal[left] = val2;
traversal[right] = val1;
left++;
right--;
}
}
}
以上是碰到的第一百四十五题,后续持续更新。感觉对你有帮助的小伙伴可以帮忙点个赞噢!