转自 剑指Offer之 - 树中两个结点的最低公共祖先

题目:

求树中两个节点的最低公共祖先。

思路一:

——如果是二叉树,而且是二叉搜索树,那么是可以找到公共节点的。

二叉搜索树都是排序过的,位于左子树的节点都比父节点小,而位于右子树上面的节点都比父节点大。

如果当前节点的值比两个结点 的值都大,那么最低的共同的父节点一定是在当前节点的左子树中,于是下一步遍历当前节点的左子节点。

如果当前节点的值比两个结点的值都小,那么最低的共同的父节点一定是在当前节点的右子树中,于是下一步遍历当前节点的右子节点。

这样从上到下,找到的第一个在两个输入结点的值之间的节点,就是最低的公共祖先。

题目和代码参考:http://blog.csdn.net/u012243115/article/details/46875537

思路二:

如果这棵树不是二叉搜索树,甚至连二叉树都不是,而只是普通的树。

——如果有指向父节点的指针,那么这个题目转换成了求,两个双向链表的第一个公共结点的问题。

思路三:

这棵树是普通的树,而且这个树中的结点没有指向父节点的指针。

——遍历这个树,看以这个节点为根的子树是否包含这两个节点,如果包含,判断这个节点的子节点是否包含,

——知道子节点都不包含而这个当前的节点包含,那么这个节点就是最低的公共祖先。

ps.这里存在大量的重复遍历,效率不高。

思路三:

这棵树是普通的树,而且这个树中的结点没有指向父节点的指针。

——用两个链表分别保存从根节点到输入的两个结点的路径,然后把问题转换成两个链表的最后公共节点。

代码:

(这里假设树是普通二叉树,用思路三求解)

#include <iostream>
#include <list>
using namespace std; struct TreeNode
{
int m_nValue;
TreeNode *m_pLeft;
TreeNode *m_pRight;
TreeNode(){}
TreeNode(int value):m_nValue(value),m_pLeft(NULL),m_pRight(NULL){}
}; //得到pNode结点的路径,放入path中 也可以用栈来实现 ,递归的本质就是一个压栈和出栈的过程
// 本题可为剑指offer原题P252,其解法可参考面试题25(P143)
bool GetNodePath(TreeNode * pRoot , TreeNode *pNode , list<TreeNode *> &path)
{
if(pRoot == NULL)
return false;
path.push_back(pRoot); bool found = false;
if(pRoot == pNode)
{
found = true;
return found;
}
// 注意理解这里的递归问题
found = GetNodePath(pRoot->m_pLeft , pNode , path) || GetNodePath(pRoot->m_pRight , pNode , path);
if(!found)
path.pop_back();
return found;
} //找到两条路径的最后一个公共结点即是公共祖先
TreeNode * GetLastCommonNode(const list<TreeNode *> &path1 , const list<TreeNode*> &path2)
{
list<TreeNode *>::const_iterator iterator1 = path1.begin();
list<TreeNode *>::const_iterator iterator2 = path2.begin();
TreeNode *pLast = NULL;
while(iterator1 != path1.end() && iterator2 != path2.end())
{
if(*iterator1 == *iterator2)
pLast = *iterator1;
iterator1++;
iterator2++;
}
return pLast;
} TreeNode * GetLastCommonNodeParent(TreeNode *pRoot , TreeNode *pNode1 , TreeNode *pNode2)
{
if(pRoot == NULL || pNode1 == NULL || pNode2 == NULL)
return NULL;
list<TreeNode *> path1;
GetNodePath(pRoot , pNode1 , path1);
list<TreeNode *> path2;
GetNodePath(pRoot , pNode2 , path2);
return GetLastCommonNode(path1 , path2);
} TreeNode * findLCA(TreeNode *pRoot , TreeNode *pNode1 , TreeNode *pNode2)
{
if(pRoot == NULL)
return NULL;
if(pRoot == pNode1 || pRoot == pNode2)
return pRoot;
TreeNode *left_lca = findLCA(pRoot->m_pLeft , pNode1 , pNode2);
TreeNode *right_lca = findLCA(pRoot->m_pRight , pNode1 , pNode2);
if(left_lca && right_lca )
return pRoot;
return (left_lca != NULL) ? left_lca : right_lca;
} int main()
{
TreeNode *p1 = new TreeNode();
TreeNode *p2 = new TreeNode();
TreeNode *p3 = new TreeNode();
TreeNode *p4 = new TreeNode();
TreeNode *p5 = new TreeNode();
TreeNode *p6 = new TreeNode();
TreeNode *p7 = new TreeNode();
TreeNode *p8 = new TreeNode();
TreeNode *p9 = new TreeNode();
TreeNode *p10 = new TreeNode();
p1->m_pLeft = p2;
p1->m_pRight = p3;
p2->m_pLeft = p4;
p2->m_pRight = p5;
p3->m_pLeft = p6;
p3->m_pRight = p7;
p4->m_pLeft = p8;
p4->m_pRight = p9;
p5->m_pLeft = p10;
TreeNode *p;
p = GetLastCommonNodeParent(p1 , p8 , p7);//p8和p7的最近公共祖先
if(p)
cout<<"最近的公共祖先是p"<<p->m_nValue<<endl;
else
cout<<"不存在公共祖先"<<endl;
TreeNode *q;
q = findLCA(p1 , p8 , p7);//p8和p7的最近公共祖先
if(q)
cout<<"最近的公共祖先是p"<<q->m_nValue<<endl;
else
cout<<"不存在公共祖先"<<endl;
}

findLCA参考:http://www.acmerblog.com/lca-lowest-common-ancestor-5574.html

寻找二叉树中的最低公共祖先结点----LCA(Lowest Common Ancestor )问题(递归)的更多相关文章

  1. 最近公共祖先问题 LCA

    2018-03-10 18:04:55 在图论和计算机科学中,最近公共祖先,LCA(Lowest Common Ancestor)是指在一个树或者有向无环图中同时拥有v和w作为后代的最深的节点. 计算 ...

  2. 二叉树系列 - 求两节点的最低公共祖先,例 剑指Offer 50

    前言 本篇是对二叉树系列中求最低公共祖先类题目的讨论. 题目 对于给定二叉树,输入两个树节点,求它们的最低公共祖先. 思考:这其实并不单单是一道题目,解题的过程中,要先弄清楚这棵二叉树有没有一些特殊的 ...

  3. 树中两个结点的最低公共祖先--java

    题目:对于任意一个树,不仅仅限于二叉树,求树中两个结点的最低公共祖先结点. 解析:对于任意一棵树,显然并不局限于二叉树,也就是说树的非叶子结点可能存在多个子节点.所以,我们可以定义两个链表结构,存储这 ...

  4. 【Java】 剑指offer(68) 树中两个结点的最低公共祖先

      本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集   题目 输入两个树结点,求它们的最低公共祖先. 思路 该题首先要和面试 ...

  5. 剑指Offer - 九度1509 - 树中两个结点的最低公共祖先

    剑指Offer - 九度1509 - 树中两个结点的最低公共祖先2014-02-07 01:04 题目描述: 给定一棵树,同时给出树中的两个结点,求它们的最低公共祖先. 输入: 输入可能包含多个测试样 ...

  6. 【Offer】[68] 【树中两个结点的最低公共祖先】

    题目描述 思路分析 测试用例 Java代码 代码链接 题目描述 输入两个树结点,求它们的最低公共祖先. [牛客网刷题地址]无 思路分析 该题首先要确定是否为二叉树,还要确定是否为二叉搜索树,是否有父指 ...

  7. 【剑指Offer面试编程题】题目1509:树中两个结点的最低公共祖先--九度OJ

    题目描述: 给定一棵树,同时给出树中的两个结点,求它们的最低公共祖先. 输入: 输入可能包含多个测试样例. 对于每个测试案例,输入的第一行为一个数n(0<n<1000),代表测试样例的个数 ...

  8. 最近公共祖先:LCA及其用倍增实现 +POJ1986

    Q:为什么我在有些地方看到的是最小公共祖先? A:最小公共祖先是LCA(Least Common Ancestor)的英文直译,最小公共祖先与最近公共祖先只是叫法不同. Q:什么是最近公共祖先(LCA ...

  9. LeetCode 235. Lowest Common Ancestor of a Binary Search Tree (二叉搜索树最近的共同祖先)

    Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BS ...

随机推荐

  1. 【CUDA】Win10 + VS2017新 CUDA 项目配置

    一.新建项目 打开VS2017 → 新建项目 → Win32控制台应用程序 → “空项目”打钩 二.调整配置管理器平台类型 右键项目 → 属性 → 配置管理器 → 全改为“x64” 三.配置生成属性 ...

  2. python报错函数传参数传多了

    写python的时候报错: Exception : Traceback (most recent call last): File , in __bootstrap_inner self.run() ...

  3. let,const 声明的变量不会绑定给window对象 而var会

    先来看一道题 let id = 2; let json = { id: 1, show:function(){ setTimeout(function(){ console.log(this.id); ...

  4. redis可执行文件说明

    redis-server    :redis服务器 redis-cli    :redis命令客户端 redis-benchmark    :redis性能压测工具 redis-check-dump ...

  5. 【ANT】输入中文格式为乱码

    使用ant编译,打出的日志的格式为乱码,加上下面的指定编码后,输出为中文了. 为方便拷贝,将其贴出来 <jvmarg value="-Dfile.encoding=UTF-8" ...

  6. coursera-斯坦福-机器学习-吴恩达-笔记week1

    1 Introduction 1.1 概念:一个程序被认为能从经验E中学习,解决任务 T,达到性能度量值P,当且仅当, 有了经验E后,经过P评判, 程序在处理 T 时的性能有所提升. 1.2 机器学习 ...

  7. 蒙特·卡罗方法(Monte Carlo method)

    蒙特·卡罗方法(Monte Carlo method),也称统计模拟方法,是二十世纪四十年代中期由于科学技术的发展和电子计算机的发明,而被提出的一种以概率统计理论为指导的一类非常重要的数值计算方法.是 ...

  8. JVM配置参数详解

    记录一下jvm中的一些配置参数,这些肯定不全的,希望你们能留个言,补全一下,谢谢啦! -XX: MaxDirectMemorySize--->设置直接内存,不设置与Java堆内存最大值一致 -X ...

  9. Codeforces Round #244 (Div. 2) C. Checkposts (tarjan 强连通分量)

    题目:http://codeforces.com/problemset/problem/427/C 题意:给你n座城市,m条有向道路,然后有一个机制,你在某一个城市设置检查点,那么被设置的检查点受保护 ...

  10. void的几点用法

    1.可以通过void 0 获取undefined.等同于void(0). void 任意数 === undefined   // true void(0) === undefined  // true ...