《剑指Offer》面试题:重构二叉树
来源:互联网 发布:杭州市物联网产业数据 编辑:程序博客网 时间:2024/06/05 01:20
题目描述:
输入某二叉树的前序遍历和中序遍历的结果,
请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并输出它的后序遍历序列。
思路
根据前序遍历的数组,arr[0]为根节点,在中序遍历中找到值等于arr[0]的位置index,则index的左边为此节点的左子树,右边为此节点的右子树。于是递归构建该节点的左右子树。
需要考虑的测试用例
1)一个结点的数
2)只有左子树的树
3)只有右子树的树
4)普通的树
5)特殊输入
/*输入:输入可能包含多个测试样例,对于每个测试案例,输入的第一行为一个整数n(1<=n<=1000):代表二叉树的节点个数。输入的第二行包括n个整数(其中每个元素a的范围为(1<=a<=1000)):代表二叉树的前序遍历序列。输入的第三行包括n个整数(其中每个元素a的范围为(1<=a<=1000)):代表二叉树的中序遍历序列。输出:对应每个测试案例,输出一行:如果题目中所给的前序和中序遍历序列能构成一棵二叉树,则输出n个整数,代表二叉树的后序遍历序列,每个元素后面都有空格。如果题目中所给的前序和中序遍历序列不能构成一棵二叉树,则输出”No”。样例输入:81 2 4 7 3 5 6 84 7 2 1 5 3 8 681 2 4 7 3 5 6 84 1 2 7 5 3 8 6样例输出:7 4 2 5 8 6 3 1 No*/ #include<stdio.h>#include<stdlib.h>struct TreeNode{ int mValue; struct TreeNode *lchild; struct TreeNode *rchild;};bool canRebuild;/*函数的功能:根据树的前序遍历、中序遍历来重构二叉树。参数的说明@param pRoot:即将重构的Tree的头结点的指针。@param n:节点的个数@param preTraversal :前序遍历的数组。 @param inTraversal:后序遍历的数组 */void rebuildBTree(TreeNode **pRoot,int len,int *preTraversal,int *inTraversal){ if(preTraversal==NULL||inTraversal==NULL) { canRebuild=false; return ; } // if(len<1){ return; } //在中序遍历中找到前序遍历的头结点的左右子结点 int index=-1; for(int i=0;i<len;i++){ if(preTraversal[0]==inTraversal[i]){ index=i; break; } } if(index==-1){//这种情况就是没有找到当前根结点在中序遍历的位置。因此不能重构 canRebuild=false; return; } //找到了之后就开始构建此结点 //为当前结点分配空间 (*pRoot)=(TreeNode *)malloc(sizeof(struct TreeNode)); if((*pRoot)==NULL){ exit(EXIT_FAILURE); } (*pRoot)->mValue=preTraversal[0]; (*pRoot)->lchild=NULL; (*pRoot)->rchild=NULL; //接下来开始构建该结点的左右子树。 rebuildBTree(&((*pRoot)->lchild),index,preTraversal+1,inTraversal); rebuildBTree(&((*pRoot)->rchild),len-index-1,preTraversal+index+1,inTraversal+index+1); }//按后序遍历输出二叉树 void postTraversal(TreeNode *pRoot){ if(pRoot==NULL){ return; } if(pRoot->lchild!=NULL){ postTraversal(pRoot->lchild); } if(pRoot->rchild!=NULL){ postTraversal(pRoot->rchild); } printf("%d ",pRoot->mValue);}void destoryBTree(TreeNode* pRoot){ if(pRoot==NULL){ return; } destoryBTree(pRoot->lchild); destoryBTree(pRoot->rchild); if(pRoot->lchild==NULL||pRoot->rchild==NULL){ free(pRoot); pRoot=NULL; } return;}int main(void){ int n; while(scanf("%d",&n)&&n>0){ int *preTraversal=(int *)malloc(n*sizeof(int)); int *inTraversal=(int *)malloc(n*sizeof(int)); if(preTraversal==NULL||inTraversal==NULL){ exit(EXIT_FAILURE); } for(int i=0;i<n;i++){ scanf("%d",preTraversal+i); } for(int i=0;i<n;i++){ scanf("%d",inTraversal+i); } //重构二叉树 TreeNode *pRoot; bool canRebuild=true; rebuildBTree(&pRoot,n,preTraversal,inTraversal) ; if(canRebuild){ //按后序遍历输出 postTraversal(pRoot); printf("\n"); } else{ printf("No\n"); } //最后销毁二叉树 destoryBTree(pRoot); free(preTraversal); preTraversal=NULL; free(inTraversal); inTraversal=NULL; } return 0;}
今天和同学聊起这个题,说不知道用Java如何来重建二叉树,于是就写了下,代码如下,2016年8月23日16:20:20
public class RebuildTree2 { private static boolean canRebuild = true; private static int[] postOrder ; private static int indexPost = 0; public TreeNode reConstructBinaryTree(int [] pre,int [] in) { if(pre==null||in==null||pre.length!=in.length){ return null; } TreeNode head = rebuildHelper(pre,in,pre.length); if(!canRebuild){//不能重建 return null; } return head; } private TreeNode rebuildHelper(int[] pre, int[] in, int len) { if(pre==null||in==null||len<1){ //canRebuild = false; return null; } int val = pre[0];//根节点 //在中序遍历中找到头结点出现的位置 int index = -1; for(int i=0;i<len;i++){ if(in[i]==val){ index = i; break; } } if(index==-1){//在中序遍历中没有找到根节点,因此不能重建 canRebuild = false; return null; } //构建当前根节点 TreeNode head = new TreeNode(val); //接着开始构建根节点的左右子树 //左子树 //先进行数组的拷贝 int len1 = index ; int[] preNew = new int[len1]; int[] inNew = new int[len1]; for(int i=0;i<len1;i++){ preNew[i] = pre[1+i]; inNew[i] = in[i]; } head.left = rebuildHelper(preNew, inNew,len1); //检查左子树是否能够重建 if(!canRebuild){ return null; } //右子树 //先进行数组的拷贝 int len2 = len-index-1; int[] preNew2 = new int[len2]; int[] inNew2 = new int[len2]; for(int i=0;i<len2;i++){ preNew2[i] = pre[index+1+i]; inNew2[i] = in[index+1+i]; } head.right = rebuildHelper(preNew2, inNew2,len2); return head; } public static void main(String[] args){ int len = 7; int[] pre = {1,2,3,4,5,6,7}; int[] in = {3,2,4,1,6,5,7}; postOrder = new int[len]; RebuildTree2 bt = new RebuildTree2(); TreeNode head = bt.reConstructBinaryTree(pre,in); System.out.println(head.val); //后序遍历 bt.postOrder(head); for(int i=0;i<len;i++){ System.out.print(postOrder[i]+" "); } } private void postOrder(TreeNode head) { if(head==null){ return ; } if(head.left!=null){ postOrder(head.left); } if(head.right!=null){ postOrder(head.right); } postOrder[indexPost] = head.val; indexPost++; //System.out.print(head.val+" "); }}
1 0
- 《剑指Offer》面试题:重构二叉树
- 剑指offer面试题6 重构二叉树
- 剑指Offer——面试题6:重构二叉树
- 《剑指Offer》面试题-重建二叉树
- 《剑指Offer》面试题:平衡二叉树
- 面试题之重构二叉树
- 剑指offer面试题6 前序遍历&中序遍历,后序遍历&中序遍历重构二叉树
- 剑指offer--面试题6: 重建二叉树(树)
- 剑指offer-->面试题6 重建二叉树
- [剑指offer][面试题06]重建二叉树
- [剑指offer][面试题19]二叉树的镜像
- [剑指offer][面试题39]二叉树的深度
- 【剑指offer】面试题6:重建二叉树
- 【剑指offer】面试题19:二叉树的镜像
- 《剑指offer》面试题6:重建二叉树
- 【剑指offer】面试题39:二叉树的深度
- 剑指offer 面试题6 重建二叉树
- 剑指offer 面试题19 二叉树的镜像
- jQuery实现打印输出字体
- 我的CSDN博客三周年------不是坚持, 而是热爱!
- intellij idea之servlet
- 如何完全卸载SQL SERVER?
- hdu5504
- 《剑指Offer》面试题:重构二叉树
- 黑马程序员——GUI
- Amazon OA1准备——去元音
- 图片像素、大小、分辨率的关系
- 【Android】Activity右滑返回的实现
- 2015 毕业秋招感慨
- java使用javamail读取邮箱(收件箱为例)
- 可视化日历
- 正则表达式的问题收集