剑指offer--<重建二叉树>
2017-03-19 15:46
309 查看
题目描述:
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
题目条件:数组前序+数组中序
题目要求:重现二维数组
理论知识:二叉树,前序遍历 ,中序遍历 ,一开始忘了前序遍历和中序遍历,翻了一下数据结构,前序遍历,先处理当前节点,再处理左子树,最后处理右子树,中序遍历,先处理左子树,再处理当前节点,最后处理右子树,附:前,中,后是指的当前节点。
自己思路:
1. 前序遍历,先处理当前节点,所以,比较容易找节点,中序遍历的有个明显的特点,就是当前节点的左子树,就在当前节点的左边,所以先找根节点,通过前序遍历来确定根节点,子树根节点,中序遍历来确定,属于左子树还是右子树。
2.第一次执行程序之后,可以得到根节点,左子树和右子树,将左子树(右子树)继续当做一棵树(递归),继续执行程序,就可以确定每个节点。
3. 思考的过程中,发现确定根节点的过程类似于快速排序实现,每次递归。
具体代码(原创):
再贴一下,牛客呼声比较高的代码:
代码 托管GitHub:https://github.com/johnlee2018/JZoffer.git
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
题目条件:数组前序+数组中序
题目要求:重现二维数组
理论知识:二叉树,前序遍历 ,中序遍历 ,一开始忘了前序遍历和中序遍历,翻了一下数据结构,前序遍历,先处理当前节点,再处理左子树,最后处理右子树,中序遍历,先处理左子树,再处理当前节点,最后处理右子树,附:前,中,后是指的当前节点。
自己思路:
1. 前序遍历,先处理当前节点,所以,比较容易找节点,中序遍历的有个明显的特点,就是当前节点的左子树,就在当前节点的左边,所以先找根节点,通过前序遍历来确定根节点,子树根节点,中序遍历来确定,属于左子树还是右子树。
2.第一次执行程序之后,可以得到根节点,左子树和右子树,将左子树(右子树)继续当做一棵树(递归),继续执行程序,就可以确定每个节点。
3. 思考的过程中,发现确定根节点的过程类似于快速排序实现,每次递归。
具体代码(原创):
/** * Definition for binary tree * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class Solution { public TreeNode reConstructBinaryTree(int [] pre,int [] in) { //pre,in的大小始终是相同的。 TreeNode root=null; if (pre.length==0)//处理空树 { return root; } root=getTree(pre,in);//放入参数,进行递归处理 return root; } //前序遍历{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6} private TreeNode getTree(int[] pre, int[] in) { TreeNode treeNode= new TreeNode(pre[0]);//通过前序找好子树根节点 if (pre.length==1)//处理树中只有一个根节点 { treeNode.left=null; treeNode.right=null; return treeNode; } int irank=getIrank(0,pre,in);//确定数的根节点在中序的下标 if ((irank>0)&(irank<pre.length-1))//树有左子树and右子树 { int[] plow=new int[irank];//low 代表左子树部分,左子树前序列表 int[] ilow=new int[irank];//左子树中序列表 int[] phigh=new int[in b533 .length-irank-1];//high 代表右子树部分,右子树前序列表 int[] ihigh=new int[in.length-irank-1];//high 代表右子树部分,右子树中序列表 ilow://根据子树跟节点切分中序得到左边部分 for (int i=0;i<irank;i++ ) { ilow[i]=in[i]; } plow://根据子树跟节点切分前序得到左边部分 for (int i=0;i<irank;i++ ) { plow[i]=pre[i+1]; } treeNode.left=getTree(plow,ilow);//左子树递归 ihigh://根据子树跟节点切分中序得到右边部分 for (int i=irank+1;i<in.length;i++ ) { ihigh[i-irank-1]=in[i]; } phigh://根据子树跟节点切分中序得到右边部分 for (int i=irank+1;i<pre.length;i++ ) { phigh[i-irank-1]=pre[i]; } treeNode.right=getTree(phigh,ihigh);//you右子树递归 } else if((irank>0))////树有左子树 { int[] plow=new int[irank]; int[] ilow=new int[irank]; ilow://根据子树跟节点切分中序得到左边部分 for (int i=0;i<irank;i++ ) { ilow[i]=in[i]; } plow://根据子树跟节点切分前序得到左边部分 for (int i=0;i<irank;i++ ) { plow[i]=pre[i+1]; } treeNode.right=null; treeNode.left=getTree(plow,ilow); } else if(irank<pre.length-1)//树有右子树 { //int[] plow=new int[irank]; //int[] ilow=new int[irank]; int[] ihigh=new int[in.length-irank-1]; int[] phigh=new int[in.length-irank-1]; ihigh://根据子树跟节点切分中序得到右边部分 for (int i=irank+1;i<in.length;i++ ) { ihigh[i-irank-1]=in[i]; } phigh://根据子树跟节点切分中序得到右边部分 for (int i=irank+1;i<pre.length;i++ ) { phigh[i-irank-1]=pre[i]; } treeNode.left=null; treeNode.right=getTree(phigh,ihigh); } return treeNode; } private int getIrank(int prank,int[] pre, int[] in) { for (int i=0;i<in.length;i++) { if(pre[prank]==in[i]) { return i; } } return prank; } }
再贴一下,牛客呼声比较高的代码:
/** * Definition for binary tree * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class Solution { public TreeNode reConstructBinaryTree(int [] pre,int [] in) { TreeNode root=reConstructBinaryTree(pre,0,pre.length-1,in,0,in.length-1);//启动 return root; } //前序遍历{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6} private TreeNode reConstructBinaryTree(int [] pre,int startPre,int endPre,int [] in,int startIn,int endIn) { if(startPre>endPre||startIn>endIn) return null; TreeNode root=new TreeNode(pre[startPre]);//每次都是用原来的pre,而我的是每次都生成一个新的,这个更好 for(int i=startIn;i<=endIn;i++)//还存在子树 if(in[i]==pre[startPre])//找到根节点位置i { root.left=reConstructBinaryTree(pre,startPre+1,startPre+i-startIn,in,startIn,i-1);//这一步,锁定下一次循环的前序和中序序列 root.right=reConstructBinaryTree(pre,i-startIn+startPre+1,endPre,in,i+1,endIn); } return root; } }
代码 托管GitHub:https://github.com/johnlee2018/JZoffer.git
相关文章推荐
- 剑指offer-->面试题6 重建二叉树
- <剑指offer 面试题7-2>重建二叉树 Java
- <剑指offer 面试题8>二叉树的下一个节点(Java)
- 重建二叉树 (剑指Offer 第 4 题)
- 【剑指Offer面试题】 九度OJ1385:重建二叉树
- 剑指Offer面试题6(Java版):重建二叉树
- 剑指OFFER之重建二叉树(九度OJ1385)
- 【剑指Offer学习】【面试题6 :重建二叉树】
- 剑指offer刷题之c++实现的根据二叉树的前序和中序遍历重建二叉树
- 【剑指offer】面试题7:重建二叉树
- 剑指offer 6 重建二叉树
- 【九度OJ1385】|【剑指offer6】重建二叉树
- 剑指offer 面试题6 重建二叉树2
- 剑指offer--重建二叉树
- 剑指Offer学习总结-重建二叉树
- 剑指offer面试题6--重建二叉树
- 牛客网-剑指offer-04-重建二叉树
- 剑指offer--(4) 重建二叉树
- 剑指offer 重建二叉树
- 剑指offer 重建二叉树