《剑指Offer》面试题:树中两结点最低公共祖先
来源:互联网 发布:mac不能玩qq游戏 编辑:程序博客网 时间:2024/06/04 23:33
题目描述:
给定一棵树,同时给出树中的两个结点,求它们的最低公共祖先。
思路
这类的题目,方法蛮多的,思路也不难理解,基本都是各种遍历的变种,主要是写代码,尤其基于递归的代码。
首先如果是二叉排序树自然不用说了,判断的一句就是该节点的值是否位于输入的这两个节点之间,可以用前序遍历来做。
如果是普通的树或者二叉树,解题思路是一样的,可以考虑前序遍历,得到两个路径,用链表或数组保存起来,然后找出两条路径的最后一个公共节点即可。
也可以后序遍历的方式,遍历到输入的节点时,将该节点及其后面遍历到的节点都保存到一个链表或数组中,然后找出两条路径的第一个公共机节点即可。
下面利用前序遍历和后续遍历寻找节点在树中的路径,都进行了编码实现。
/*输入:输入可能包含多个测试样例。对于每个测试案例,输入的第一行为一个数n(0<n<1000),代表测试样例的个数。其中每个测试样例包括两行,第一行为一个二叉树的先序遍历序列,其中左右子树若为空则用0代替,其中二叉树的结点个数node_num<10000。第二行为树中的两个结点的值m1与m2(0<m1,m2<10000)。输出:对应每个测试案例,输出给定的树中两个结点的最低公共祖先结点的值,若两个给定结点无最低公共祖先,则输出“My God”。样例输入:21 2 4 6 0 0 7 0 0 5 8 0 0 9 0 0 3 0 06 81 2 4 6 0 0 7 0 0 5 8 0 0 9 0 0 3 0 06 12样例输出:2My God*/#include<stdio.h>#include<stdlib.h>struct TreeNode{ int mValue; struct TreeNode *lchild; struct TreeNode *rchild;};void createTree(TreeNode **ppNode){ int val; scanf("%d",&val); if(val==0){ *ppNode=NULL; } else{ //为新结点开辟空间。 (*ppNode)=(TreeNode *)malloc(sizeof(struct TreeNode)); if((*ppNode)==NULL){ exit(EXIT_FAILURE); } (*ppNode)->mValue=val; (*ppNode)->lchild=NULL; (*ppNode)->rchild=NULL; createTree(&((*ppNode)->lchild)); createTree(&((*ppNode)->rchild)); }} //在树中找到data的路径并保存在path1数组中。/*函数参数的说明@param pRoot:节点的指针@param data:待查找的结点的value值@param index:数组的下标索引。即该节点将存储在数组的位置@param len:用来保存最终数组中存储的节点数目。 */ bool getNodePath(TreeNode *pRoot,int *path,int data,int index,int *len){ if(pRoot==NULL){ return false; } //利用先序遍历来寻找data存在节点的路径 //第一步:当前结点保存在数组中 path[index]=pRoot->mValue; //第二步:检查当前结点是否是我们需找的节点。 if(data==path[index]){ *len=index+1; return true; } else{ bool isExist=getNodePath(pRoot->lchild,path, data,index+1,len); if(!isExist){ isExist=getNodePath(pRoot->rchild,path,data,index+1,len); } return isExist; }} //返回的是第一个公共节点在数组中的下标。,由于公共节点在两个数组前几个相同的元素都为公共节点,因此每个公共节点在在两个数组中的下标是相同的。 int findPublicNode(int *path1,int *path2,int len1,int len2){ if(path1==NULL||path2==NULL||len1<1||len2<1){ return -1; } //以下思路与求链表的第一个公共节点比较类似 //第一步:将找出大树组、小数组 int *lengthPath=path1; int *shortPath=path2; int longthLen=len1; int shortLen=len2; if(len1<len2){ lengthPath=path2; shortPath=path1; longthLen=len2; shortLen=len1; } //从后往前找,当然也可以从前往后找,一样。 for(int i=shortLen-1;i>=0;i--){ if(lengthPath[i]==shortPath[i]){ return i; } } return -1; } void destoryTree(TreeNode **pRoot){ if(*pRoot==NULL) return; //按照后序遍历来进行销毁 destoryTree(&((*pRoot)->lchild)); destoryTree(&((*pRoot)->rchild)); if((*pRoot)->lchild==NULL&&(*pRoot)->rchild==NULL){ free(*pRoot); (*pRoot)=NULL; }}int main(void){ //借助两个数组来保存遍历的路径。 int path1[10000]; int path2[10000]; int n;//测试用例的个数 while(scanf("%d",&n)!=EOF&&n>0){ for(int i=0;i<n;i++){ TreeNode *pRoot; //根据输入来创建一个树。 createTree(&pRoot); //接收待查找的节点 int first,second; scanf("%d%d",&first,&second); //寻找第一个公共结点 int len1=0; int len2=0; bool isExist1=getNodePath(pRoot,path1,first,0,&len1); bool isExist2=getNodePath(pRoot,path2,second,0,&len2); if(!(isExist1&&isExist2)){ printf("My God\n"); } else{ //在两个路径数组中找出公共结点的value值。 int publicNodeIndex=findPublicNode(path1,path2,len1,len2); if(publicNodeIndex!=-1){ printf("%d\n",path1[publicNodeIndex]); } else{ printf("My God\n"); } } //最后销毁树的内存空间 destoryTree(&pRoot); } } return 0;}
运行截图如下:
上面是利用先序遍历来寻找节点在树中的路径,下面是利用后序遍历来做,这里*len的是最大的下标。
// bool getNodePath(TreeNode *pRoot,int *path,int data,int *len){ if(pRoot==NULL){ return false; } bool isExist=getNodePath(pRoot->lchild,path, data,len); if(!isExist){ isExist=getNodePath(pRoot->rchild,path, data,len); } if(isExist){//如果其的子节点存在路径中,则此节点也肯定存在路径中。 path[++(*len)]=pRoot->mValue; } if(pRoot->mValue==data){ *len=0; path[*len]=pRoot->mValue; return true; } return isExist;}
0 0
- 《剑指Offer》面试题:树中两结点最低公共祖先
- 《剑指offer》面试题50 树中两个结点的最低公共祖先
- 《剑指Offer》学习笔记--面试题50:树中两个结点的最低公共祖先
- 【剑指offer】 面试题50: 树中两个结点的最低公共祖先
- 【剑指Offer学习】【面试题50:树中两个结点的最低公共祖先】
- 剑指offer面试题:求树中两个结点的最低公共祖先
- 剑指offer之面试题50树中两个结点的最低公共祖先
- 剑指offer--面试题50:树中两个结点的最低公共祖先
- 剑指offer——面试题50:树中两个结点的最低公共祖先
- 剑指offer-面试题50-树中两个结点的最低公共祖先
- 剑指offer 面试题50 树中两个结点的最低公共祖先
- 剑指Offer面试题49字符串转整数,面试题50二叉树两个结点的最低公共祖先
- 【剑指offer】 面试题50: 树中两个结点的最低公共祖先(二叉排序数)
- 《剑指offer》树中两个结点的最低公共祖先
- 剑指offer面试题50!!!树中两个最低公共祖先
- [剑指offer][面试题50]树中两个节点的最低公共祖先
- 剑指Offer:面试题50 树中两个节点的最低公共祖先
- 剑指offer 面试题50—树中两个节点的最低公共祖先
- 原码、反码、补码详解
- 写模板--Smarty类的编译功能仿写
- 6个Java项目UML反向工程工具
- 解决os x el capitan proxychains 不能用 (关闭SIP)
- c语言的基础数据类型
- 《剑指Offer》面试题:树中两结点最低公共祖先
- ORACLE CONNECT BY 整理
- IOS开发-C语言基础篇
- 一、VBScript 简介
- 提高Interface Builder高效工作的8个技巧
- 我的研究生生涯
- Android 应用开发一般都安装个版本的 SDK ?
- Eclipse 插件 ModelGoon 安装(含Eclipse代理设置)
- ios入门攻略 02篇 C语言基础【常量、变量、scanf函数、算术运算】