根据一棵树的前序遍历与中序遍历构造二叉树
方法一:使用栈解决
如果使用栈来解决首先要搞懂一个知识点,就是前序遍历挨着的两个值比如m和n,他们会有下面两种情况之一的关系。
1,n是m左子树节点的值。
2,n是m右子树节点的值或者是m某个祖先节点的右节点的值。
对于第一个知识点我们很容易理解,如果m的左子树不为空,那么n就是m左子树节点的值。
对于第二个问题,如果一个结点没有左子树只有右子树,那么n就是m右子树节点的值,如果一个结点既没有左子树也没有右子树,那么n就是m某个祖先节点的右节点,我们只要找到这个祖先节点就好办了。
搞懂了这点,代码就很容易写了,下面看下完整代码
public TreeNode buildTree(int[] preorder, int[] inorder) { if (preorder.length == 0) return null; Stack<TreeNode> s = new Stack<>(); //前序的第一个其实就是根节点 TreeNode root = new TreeNode(preorder[0]); TreeNode cur = root; for (int i = 1, j = 0; i < preorder.length; i++) { //第一种情况 if (cur.val != inorder[j]) { cur.left = new TreeNode(preorder[i]); s.push(cur); cur = cur.left; } else { //第二种情况 j++; //找到合适的cur,然后确定他的右节点 while (!s.empty() && s.peek().val == inorder[j]) { cur = s.pop(); j++; } //给cur添加右节点 cur = cur.right = new TreeNode(preorder[i]); } } return root; }
方法二:递归法
class Solution { private int in = 0; private int pre = 0; private int[] preorder; private int[] inorder; public TreeNode buildTree(int[] preorder, int[] inorder) { this.preorder = preorder; this.inorder = inorder; return build(Integer.MIN_VALUE); } private TreeNode build(int stop) { if (pre >= preorder.length) return null; if (inorder[in] == stop) { in++; return null; } TreeNode node = new TreeNode(preorder[pre++]); node.left = build(node.val); //左子树 当中序遍历下一节点与前序遍历相同时,到达叶节点 node.right = build(stop); //右子树 当中序遍历下一节点为当前节点的根节点时,到达叶节点 return node; }