《剑指offer》:[50]树中两个结点的最低公共祖先结点
来源:互联网 发布:淘宝新手怎么开直通车 编辑:程序博客网 时间:2024/04/29 09:40
题目:树中两个结点的最低公共祖先
该题目根据条件的不同,所使用的方案也不同。
条件一:是二叉搜索树。
方案:这种情况相对来说是最简单的,如果是二叉搜索树,则树里的数据特点比较明显。左边的比根结点小,右边的比根结点大。所以其最低的公共结点就是第一个在这两个输入节点之间的结点。
条件二:如果这棵树是一颗普通的树,可能连二叉树都不算,但是有指向父节点的指针。
方案:其实这个问题可以转化为:求两个链表的公共结点,因为有指向父节点的指针,那么给的结点就在一个链表上,我们就可以查找这两个链表的第一个公共结点。查找两个链表的公共结点,我们已经在【5】中讲的比较详细了,这里就不多做介绍了!
条件三:这棵树是一棵普通的树,可能连二叉树都不是,也没有指向父节点的指针。
方案一:由于数据不是有序,也没有指向父节点的指针,也可能是N叉树,所以我们的初步想法是,逐个结点的找,如果发现一个结点包含输入的两个结点,则顺序遍历该结点的子结点,如果子节点是最后一个包含这两个输入结点的结点,它的子结点都不包含输入的两个子结点,则说明该结点是这两个输入结点的最低公共结点。
该题目根据条件的不同,所使用的方案也不同。
条件一:是二叉搜索树。
方案:这种情况相对来说是最简单的,如果是二叉搜索树,则树里的数据特点比较明显。左边的比根结点小,右边的比根结点大。所以其最低的公共结点就是第一个在这两个输入节点之间的结点。
条件二:如果这棵树是一颗普通的树,可能连二叉树都不算,但是有指向父节点的指针。
方案:其实这个问题可以转化为:求两个链表的公共结点,因为有指向父节点的指针,那么给的结点就在一个链表上,我们就可以查找这两个链表的第一个公共结点。查找两个链表的公共结点,我们已经在【5】中讲的比较详细了,这里就不多做介绍了!
条件三:这棵树是一棵普通的树,可能连二叉树都不是,也没有指向父节点的指针。
方案一:由于数据不是有序,也没有指向父节点的指针,也可能是N叉树,所以我们的初步想法是,逐个结点的找,如果发现一个结点包含输入的两个结点,则顺序遍历该结点的子结点,如果子节点是最后一个包含这两个输入结点的结点,它的子结点都不包含输入的两个子结点,则说明该结点是这两个输入结点的最低公共结点。
该方案的弊端是重复计算,就像斐波拉切数列,以及判断平衡二叉树中存在的问题一样。举个例子来看吧!
方案二:还是转化为两个链表求公共结点。这样我们就可以避免那些多余的运算。我们可以首先遍历该树,从根结点开始,到达两个输入结点就有两条路径,这样我们就可以从输入的结点开始寻找他们的第一个公共结点,就是它们的最低公共祖先结点。
还是以上图为例:一条路径为A->B->D->F,另一条路径为A->B->E->H。所以其第一个公共结点为B,那么B就是其最低的公共祖先结点。其时间复杂度,首先找路径遍历2遍,都是O(N)。然后找公共结点其时间复杂度为:O(logN),综合其时间复杂度为:O(N)。空间复杂度为2*O(N)。
条件三中的方案二具体代码实现如下:#include <iostream>#include <list>#include <vector>using namespace std;struct BinTree{int data;BinTree *pLeft;BinTree *pRight;};list<BinTree *> path1;list<BinTree *> path2;BinTree *pRoot1=NULL;bool IsExistData1=true;bool IsExistData2=true;//递归先序创建二叉树;void CreateTree(BinTree *&root){int data;cin>>data;if(0==data)root=NULL;else{root=new BinTree;root->data=data;CreateTree(root->pLeft);CreateTree(root->pRight);}}//1.将从根结点pRoot到输入的结点值data1,data2的路径保存在链表list1和list2中;bool GetNodePath(BinTree *root,int data1,list<BinTree*> &path){if(NULL==root )return false;path.push_back(root);if(root->data==data1)return true;else{bool found=false;found=GetNodePath(root->pLeft,data1,path);if(!found)found=GetNodePath(root->pRight,data1,path);if(!found)path.pop_back();return found;}}//2.得到list1和list2公共结点;BinTree *GetLastComNode(const list<BinTree *> &list1,const list<BinTree*> &list2){list<BinTree *>::const_iterator it1=list1.begin();list<BinTree *>::const_iterator it2=list2.begin();BinTree *pLast=NULL;while(it1!=list1.end() && it2!=list2.end()){if(*it1 == *it2)pLast=*it1;it1++;it2++;}return pLast;}//3.组合1,2,返回公共结点;BinTree *GetLastCommParent(BinTree *root,int data1,int data2){if(NULL==root)return NULL;//得到路径if(!GetNodePath(root,data1,path1)){IsExistData1=false;return NULL;}if(!GetNodePath(root,data2,path2)){IsExistData2=false;return NULL;}//得到最低公共祖先;return GetLastComNode(path1,path2);}void PreOrder(BinTree *root){if(root){cout<<root->data<<" ";PreOrder(root->pLeft);PreOrder(root->pRight);}}void InOrder(BinTree *root){if(root){InOrder(root->pLeft);cout<<root->data<<" ";InOrder(root->pRight);}}void DestoryBinTree(BinTree *root){if(root){DestoryBinTree(root->pLeft);DestoryBinTree(root->pRight);delete root;root=NULL;}}int main(){int da1,da2;BinTree *result=NULL;CreateTree(pRoot1);cout<<"前序遍历:";PreOrder(pRoot1);cout<<endl;cout<<"中序遍历:";InOrder(pRoot1);cout<<endl;while(1){cin>>da1>>da2;if(0==da1 || 0==da2 )break;result=GetLastCommParent(pRoot1,da1,da2);path1.clear();path2.clear();if(IsExistData1&& IsExistData2)cout<<da1<<"和"<<da2<<"的最低公共祖先是:"<<result->data<<endl;else{if(!IsExistData1)cout<<da1<<"数据不存在!"<<endl;elsecout<<da2<<"数据不存在!"<<endl;}}DestoryBinTree(pRoot1);system("pause");return 0;}
运行结果:
树的形状:
结果:
0 0
- 《剑指offer》树中两个结点的最低公共祖先
- 《剑指offer》:[50]树中两个结点的最低公共祖先结点
- 《剑指offer》面试题50 树中两个结点的最低公共祖先
- 《剑指Offer》学习笔记--面试题50:树中两个结点的最低公共祖先
- 【剑指offer】 面试题50: 树中两个结点的最低公共祖先
- 【剑指Offer学习】【面试题50:树中两个结点的最低公共祖先】
- 剑指offer之面试题50树中两个结点的最低公共祖先
- 剑指offer--面试题50:树中两个结点的最低公共祖先
- 剑指offer——面试题50:树中两个结点的最低公共祖先
- 剑指offer-面试题50-树中两个结点的最低公共祖先
- 剑指offer 面试题50 树中两个结点的最低公共祖先
- 树中两个结点的最低公共祖先50
- 剑指Offer之 - 树中两个结点的最低公共祖先
- 树中两个结点的最低公共祖先(剑指offer!!!)
- 《剑指offer》刷题笔记(综合):树中两个结点的最低公共祖先
- 【剑指offer】 面试题50: 树中两个结点的最低公共祖先(二叉排序数)
- 树中两个结点的最低公共祖先
- 树中两个结点的最低公共祖先
- 我的第一次盲打成绩
- 节点删除
- C语言之数组做参数退化问题
- 基于MyBatis3.0.6的基本操作介绍
- [LeetCode]problem 34. Search for a Range
- 《剑指offer》:[50]树中两个结点的最低公共祖先结点
- linux下redis安装遇到的问题及解决办法
- bzoj1030 文本生成器
- springboot-内存数据库h2
- 设计模式之桥接模式
- 记事(五)
- php年月日统计代码
- Caffe代码阅读笔记(3)
- 初始Java正则匹配式