剑指offer--重构二叉树

来源:互联网 发布:域名备案买什么服务器 编辑:程序博客网 时间:2024/06/05 07:42

题目描述:

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

题目解析:

1.前序遍历:

前序遍历的规则:先根节点,后左子树,再右子树

2.中序遍历:

中序遍历的规则:先左子树,后根节点,再右子树

3.求重构二叉树:

根据二叉树,应当想当应该使用递归方式,递归的画寻找规律,根据前序遍历,中序遍历的规则,可以得到下面的图示
两种排序规则解析示意图

  1. 递归函数的设计:
    • 应当存在前序数组,起始位,结束位,中序数组,起始位,结束位
    • 根据前序起始位判断根节点,根据中序定位到根节点,然后得到左子树部分,右子树部分
    • 左子树可定位新的起始位,新的结束位,自然也可以得到中序起始位,结束位,可以持续递归
    • 递归结束条件的选择很重要:
      • 每次左子树的根节点都是上一次前序根节点的下一位,当起始位大于结束位时,可以判断无此子树,返回为空;
      • 当在中序定位不到根节点时,可以判断当前为叶子节点,返回当前节点;
  2. 注意点:
    • 每次起始位和结束位的定位应该考虑坐标在移动,因此如何统一左子树的参数计算和右子树的参数
      • 可以每次赋值左子树,右子树为新的函数,一路减少数组长度,到零界点
      • 可以每次通过计算上一次的前序根节点坐标,中序定位的根节点坐标,结束位等参数进行判断

代码:

public class Solution {    public static void main(String[] args){        Solution so=new Solution();        int[] pre=new int[]{1,2,4,7,3,5,6,8};        int[] in=new int[] {4,7,2,1,5,3,8,6};        System.out.println(so.reConstructBinaryTree(pre, in));    }    public TreeNode reConstructBinaryTree(int [] pre,int [] in) {        return rebuild(pre,0,pre.length,in,0,in.length);    }    //前序数组,前序起始位,前序结束位,后序数组,后序起始位,后序结束位    private TreeNode rebuild(int [] pre,int prestart ,int preend ,int[] in ,int instart,int inend){        //递归结束条件,叶子节点的左右节点为null;        if(prestart > preend || instart>= inend){            return null;        }        TreeNode node=new TreeNode(pre[prestart]);        //定位根节点        for(int i=instart;i<inend;i++){            if(in[i]==pre[prestart]){                //递归左子树:前序起始位+1,前序起始位+中序定位根节点的长度,中序起始位不变,中序结束位为定位到的坐标                node.left=rebuild(pre, prestart+1 , prestart+(i-instart), in ,instart,i);                //递归右子树:(前序起始位+左子树长度+1(根节点)),前序结束位不变,右子树为中序根节点+1,中序结束位保持不变                node.right=rebuild(pre,(i-instart+prestart)+1,preend,in,i+1,inend);            }        }        //当递归结束后,返回当前节点        return node;    }      public class TreeNode {          int val;          TreeNode left;          TreeNode right;          TreeNode(int x) { val = x; }          public String toString(){              return "节点:["+val+"] 左孩子:{"+left+"}   右孩子:{"+right+"}";          }      }}
0 0