LC105.从前序遍历与中序遍历中构造二叉树

题目

查看题目

解题思路

主要思路:递归思想。
主要考虑的问题:
  • 根据前序和中序遍历恢复二叉树的基本思想
  • 每次怎样划分preorder数组进行遍历
主要步骤以及细节:
  • 前序遍历数组中,从头开始,每一个都是节点,可以用来区分左右子树。
  • 找到前序遍历数组中的第一个元素,通过该值定位到中序遍历中与该点值相同位置的索引(无论是哪一种遍历,数组中的元素都是一样的,显然的)
  • 记录索引为idx,此时idx在中序遍历数组中已经将数组分成两半。
  • 使用递归,在下一次的递归中:左子树,对于preorder数组来说,从上一次的preLeft的下一个开始,遍历的长度不会超过中序遍历数组中idx的长度,即(idx - inLeft)。对inorder数组来说,从初识的inLeft开始到idx - 1的位置
  • 右子树,对于preorder数组来说,从左子树边界的下一个开始,到最后preRight。对inorder数组来说,从idx的下一个元素开始,到inorder的最后,也就是inRight

代码

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
 // 注意控制左右子树在preorder上的控制区间,痛过idx进行查找
class Solution {
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        return helper(preorder, 0, preorder.length - 1, inorder, 0, inorder.length - 1);
    }

    public TreeNode helper(int[] preorder, int preLeft, int preRight,
      int[] inorder, int inLeft, int inRight){
          // 递归终止条件
          if (inLeft > inRight || preLeft > preRight) {
              return null;
          }

          // val节点是前序遍历的第一个节点的值,也就是根节点的值
          // indx是根据val值找到的中序遍历的数组中所在值的下标
          int idx = 0; 
          int val = preorder[preLeft];
          // 构造新的root节点
          TreeNode root = new TreeNode(val);
          for(int i = inLeft; i <= inRight; i++){
              if (inorder[i] == val){
                  idx = i;
                  break;
              }
          }
        // 根据idx递归查找左右子树
        // 注意控制中序遍历的查找区间,直接直观的进行区分即可
        // helper函数中preOrder区间的确定根据的是中序遍历分开的左右子树的数量
        // preorder从当前preleft的下一个开始,遍历的个数不会超过左子树或者右子树节点的个数,所以个数为
        // idx - inLeft个节点的个数
        root.left = helper(preorder, preLeft + 1, preLeft + (idx - inLeft), 
                                inorder,inLeft ,idx - 1);
        root.right = helper(preorder, preLeft + (idx - inLeft) + 1, preRight,
                                inorder, idx + 1, inRight);
        return root;
    }
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值