[leetCode]07.重建二叉树
递归
前序遍历为:| 根结点 | 左子树 | 右子树 |
中序遍历为:| 左子树 | 根结点 | 右子树 |
以前序遍历中的根节点到中序遍历中寻找根节点,这样就能知道左右子树的长度。左右子树有符合相同的查找模式,所以可以使用递归。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
if(preorder.length == 0 || inorder.length == 0)
return null;
int startPreorder = 0, endPreorder = preorder.length - 1;
int startInorder = 0, endInorder = inorder.length - 1;
return reconstructTree(
preorder,
startPreorder,
endPreorder,
inorder,
startInorder,
endInorder);
}
private TreeNode reconstructTree(
int[] preorder,
int startPreorder,
int endPreorder,
int[] inorder,
int startInorder,
int endInorder){
int rootVal = preorder[startPreorder];
TreeNode root = new TreeNode(rootVal);
if(startPreorder == endPreorder){
return root;
}
int rootInorder = 0;
while(rootInorder <= endInorder && inorder[rootInorder] != rootVal){
++rootInorder;
}
if(inorder[rootInorder] != rootVal){
throw new RuntimeException("input error");
}
int leftNodeNums = rootInorder - startInorder;
int leftPreoderEnd = startPreorder + leftNodeNums;
if(leftNodeNums > 0){
root.left = reconstructTree(
preorder,
startPreorder+1,
leftPreoderEnd,
inorder,
startInorder,
rootInorder-1);
}
if(leftNodeNums < endPreorder - startPreorder){
root.right = reconstructTree(
preorder,
leftPreoderEnd+1,
endPreorder,
inorder,
rootInorder+1,
endInorder);
}
return root;
}
}
上面的代码使用了指针。可以通过哈希表记录中序遍历中根结点的索引,这样就能快速找到前序遍历中的根结点在中序遍历的位置
class Solution {
HashMap<Integer,Integer> map;//记录中序遍历中的结点下标
int[] preorder_copy;
public TreeNode buildTree(int[] preorder, int[] inorder) {
if(preorder.length == 0 || inorder.length == 0)
return null;
//初始化map用于快速查询根节点下标
map = new HashMap<>();
for(int i = 0; i < inorder.length; i++){
map.put(inorder[i],i);
}
preorder_copy = preorder;
return rebuild(0 ,0, inorder.length - 1);
}
private TreeNode rebuild(int preRoot, int inLeft, int inRight){
if(inLeft > inRight) return null;
TreeNode root = new TreeNode(preorder_copy[preRoot]);
int i = map.get(preorder_copy[preRoot]);
root.left = rebuild(preRoot+1,inLeft,i-1);
root.right = rebuild(preRoot + i - inLeft + 1,i+1,inRight);
return root;
}
}
迭代
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
if(preorder.length == 0 || inorder.length == 0)
return null;
TreeNode root = new TreeNode(preorder[0]);
LinkedList<TreeNode> stack = new LinkedList<>();
stack.push(root);
int index = 0;
for(int i = 1; i < preorder.length; i++){
int nextRootVal = preorder[i];//下一个结点的值
TreeNode node = stack.peek();//上一个结点
if(node.val != inorder[index]){
node.left = new TreeNode(nextRootVal);
stack.push(node.left);
}else {
while(!stack.isEmpty() && stack.peek().val == inorder[index]){
++index;
node = stack.pop();
}
node.right = new TreeNode(nextRootVal);
stack.push(node.right);
}
}
return root;
}
}