leetcode之二叉树类

重建二叉树

根据二叉树的前序遍历和中序遍历的结果,重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。

1递归

解题思路

根据先序遍历的规则根左右为了自己方便表示为:【根【左子树】【右子树】】。第一个节点肯定是根结点,首先创建根结点,然后可以根据根结点在中序遍历【【左子树】根【右子树】】中根的位置细分出左子树的长度然后采取递归求解。

代码

private Map<Integer, Integer> indexForInOrders = new HashMap<>();

public TreeNode reConstructBinaryTree(int[] pre, int[] in) {
for (int i = 0; i < in.length; i++)
indexForInOrders.put(in[i], i);
return reConstructBinaryTree(pre, 0, pre.length - 1, 0);
}

private TreeNode reConstructBinaryTree(int[] pre, int preL, int preR, int inL) {
if (preL > preR)
return null;
TreeNode root = new TreeNode(pre[preL]);
int inIndex = indexForInOrders.get(root.val);
int leftTreeSize = inIndex - inL;
root.left = reConstructBinaryTree(pre, preL + 1, preL + leftTreeSize, inL);
root.right = reConstructBinaryTree(pre, preL + leftTreeSize + 1, preR, inIndex + 1);
return root;
}

2非递归(迭代)

解题思路

递归思路对于大部分人来说应该都是比较好理解的,但是迭代法是在题解中看到的,一开始我看着说明很是迷糊,看的不是很明白。虽然明白点代码的流程但却不知为何如此(小菜鸡一枚,惭愧v-v)。后面自己画图思索一番,利用先序遍历的特点,大体上看就是从左到右,如下图所示。
在这里插入图片soda
突然豁然开朗,首先遍历先序数组,根结点很容易找出,然后就该根据根结点的下一位数字创建节点了,首先得看这个根结点有没有左子树,如有,那么可以知道在中序中的第一位一定不等于根结点的值,若等,则代表这个根结点目前处于最左边,不存在左子树(与有左子树矛盾)。那么此时这个根结点没有左子树又如何?那就再看这个根节点有没有右子树,我们就讨论有右子树的情况:假定现在根结点为途图中数字2,根据中序的特点从左到右,那么2的父节点一定不会等于中序遍历中的根结点的值的下一位,若相等,则2的父节点1应该为在2之后的最左,又与2有右子树矛盾。代码流程用一个栈和一个指针辅助进行二叉树的构造。初始时栈中存放了根节点,栈的目的也是记录根节点,指针指向中序遍历的第一个节点。

代码

public TreeNode buildTree(int[] preorder, int[] inorder) {
if (preorder == null || preorder.length == 0) {
return null;
}
TreeNode root = new TreeNode(preorder[0]);
Stack stack = new Stack();
stack.push(root);
int inorderIndex = 0;
for (int i = 1; i < preorder.length; i++) {
int preorderVal = preorder[i];
TreeNode node = stack.peek();
if (node.val != inorder[inorderIndex]){
node.left = new TreeNode(preorderVal);
stack.push(node.left);
}
else {
while (!stack.isEmpty() && stack.peek().val == inorder[inorderIndex]){
inorderIndex++;
node = stack.pop();
}
node.right = new TreeNode(preorderVal);
stack.push(node.right);
}
}
return root;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值