来源Leetcode第105题从前序与中序遍历构造二叉树
根据一棵树的前序遍历与中序遍历构造二叉树。
注意:
你可以假设树中没有重复的元素。
例如,给出
1 2
| 前序遍历 preorder = [3,9,20,15,7] 中序遍历 inorder = [9,3,15,20,7]
|
返回如下的二叉树:
递归构造
前序序列的第一个节点为根节点,根据根节点在中序序列里的位置,划分出根节点的左右子树,进一步的递归构造。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| preorder = inorder = 首先根据 preorder 找到根节点是 3 然后根据根节点将 inorder 分成左子树和右子树 左子树 inorder
右子树 inorder
把相应的前序遍历的数组也加进来 左子树 preorder inorder
右子树 preorder inorder
现在我们只需要构造左子树和右子树即可,成功把大问题化成了小问题 然后重复上边的步骤继续划分,直到 preorder 和 inorder 都为空,返回 null 即可
|
用一个Map存储中序遍历每一个节点的位置,由此确定对应的左右子树范围。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| HashMap<Integer,Integer> map = new HashMap<>(); int [] preorder,inorder; public TreeNode buildTree(int[] preorder, int[] inorder) { for(int i = 0 ; i < inorder.length ;i++) map.put(inorder[i],i); this.preorder = preorder; this.inorder = inorder; return helper(0,preorder.length ,0,inorder.length); }
private TreeNode helper(int p_start,int p_end,int i_start,int i_end){ if(p_start == p_end) return null; TreeNode root = new TreeNode(this.preorder[p_start]); int i_root_index = this.map.get(this.preorder[p_start]); int left = i_root_index - i_start; root.left = helper(p_start + 1 , p_start + left + 1,i_start,i_root_index); root.right = helper(p_start + 1 + left,p_end,i_root_index + 1 , i_end); return root; }
|
迭代 栈
来源题解
我们用一个栈保存已经遍历过的节点,遍历前序遍历的数组,一直作为当前根节点的左子树,直到当前节点和中序遍历的数组的节点相等了,那么我们正序遍历中序遍历的数组,倒着遍历已经遍历过的根节点(用栈的 pop 实现),找到最后一次相等的位置,把它作为该节点的右子树。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| public TreeNode buildTree(int[] preorder, int[] inorder) { if (preorder.length == 0) { return null; } Stack<TreeNode> roots = new Stack<TreeNode>(); int pre = 0; int in = 0; TreeNode curRoot = new TreeNode(preorder[pre]); TreeNode root = curRoot; roots.push(curRoot); pre++; while (pre < preorder.length) { if (curRoot.val == inorder[in]) { while (!roots.isEmpty() && roots.peek().val == inorder[in]) { curRoot = roots.peek(); roots.pop(); in++; } curRoot.right = new TreeNode(preorder[pre]); curRoot = curRoot.right; roots.push(curRoot); pre++; } else { curRoot.left = new TreeNode(preorder[pre]); curRoot = curRoot.left; roots.push(curRoot); pre++; } } return root; }
|