难度:中等
给定两个整数数组 preorder
和 inorder
,其中 preorder
是二叉树的先序遍历, inorder
是同一棵树的中序遍历,请构造二叉树并返回其根节点。
输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
输出: [3,9,20,null,null,15,7]
输入: preorder = [-1], inorder = [-1]
输出: [-1]
遍历前序遍历序列,对于每个值分别创建结点,将每个结点作为上一个结点的左子结点,并将每个结点入栈,直到前序遍历序列的上一个结点值等于中序遍历序列的当前结点值。然后遍历中序遍历序列并依次将栈内的结点出栈,直到栈顶结点值和中序遍历序列的当前结点值不同,此时前序遍历序列的当前值对应的结点为最后一个出栈的结点的右子结点,将当前结点入栈。然后对前序遍历序列和中序遍历序列的其余值继续执行上述操作,直到遍历结束时,二叉树构造完毕。
public class TreeNode
{
public int val;
public TreeNode left;
public TreeNode right;
public TreeNode(int val = 0, TreeNode left = null, TreeNode right = null)
{
this.val = val;
this.left = left;
this.right = right;
}
}
class Solution
{
public static void Main(string[] args)
{
int[] preorder = { 3, 9, 20, 15, 7 };
int[] inorder = { 9, 3, 15, 20, 7 };
Solution solution = new Solution();
TreeNode ans = solution.BuildTree(preorder, inorder);
List<int> tmp = new List<int>();
solution.BackTrack(ans, tmp);
foreach (var a in tmp)
{
Console.Write(a + " ");
}
}
public TreeNode BuildTree(int[] preorder, int[] inorder)
{
int length = inorder.Length;
TreeNode root = new TreeNode(preorder[0]);
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.Push(root);
int inorderIndex = 0;
for (int i = 1; i < length; i++)
{
TreeNode prev = stack.Peek();
TreeNode curr = new TreeNode(preorder[i]);
if (prev.val != inorder[inorderIndex])
{
prev.left = curr;
}
else
{
while (stack.Count > 0 && stack.Peek().val == inorder[inorderIndex])
{
prev = stack.Pop();
inorderIndex++;
}
prev.right = curr;
}
stack.Push(curr);
}
return root;
}
public void BackTrack(TreeNode root, IList<int> list)
{
if (root == null)
{
return;
}
BackTrack(root.left, list);
list.Add(root.val);
BackTrack(root.right, list);
}
}