给定一棵二叉树,找到两个节点的最近公共父节点(LCA)。
最近公共祖先是两个节点的公共的祖先节点且具有最大深度。
假设给出的两个节点都在树中存在。

dfs递归写法

查找两个node的最近公共祖先,分三种情况:

  1. 如果两个node在root的两边,那么最近公共祖先就是root。
  2. 如果两个node在root的左边,那么把root的左子树作为root,再递归。
  3. 如果两个node在root的右边,那么把root的右子树作为root,再递归。

深度优先遍历二叉树,一旦找到了两个节点其中的一个,就将这个几点返回给上一层,上一层节点通过判断其左右子树中是否恰好包含n1和n2两个节点,如果找到,对应的上一层节点肯定是所求的LCA;若果不是,将包括两个节点中任意一个的较低的节点返回给上一层,否则返回NULL。

 /**
* Definition of TreeNode:
* class TreeNode {
* public:
* int val;
* TreeNode *left, *right;
* TreeNode(int val) {
* this->val = val;
* this->left = this->right = NULL;
* }
* }
*/ class Solution {
public:
/*
* @param root: The root of the binary search tree.
* @param A: A TreeNode in a Binary.
* @param B: A TreeNode in a Binary.
* @return: Return the least common ancestor(LCA) of the two nodes.
*/
TreeNode * lowestCommonAncestor(TreeNode * root, TreeNode * A, TreeNode * B) {
// write your code here
//如果当前节点为空,或者与目标节点中的一个相同,则返回该节点
if(root == NULL) return NULL;
if(root==A || root==B) return root; //递归寻找A B在左右子树的位置
TreeNode* left = lowestCommonAncestor(root->left,A,B);
TreeNode* right = lowestCommonAncestor(root->right,A,B); //如果A B分别位于root的两侧,则root是他们的LCA,否则是左子树或者右子树
if(left&&right) return root; return left?left:right; }
};

非递归:

后序遍历非递归

 TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if (root == nullptr)
return root;
stack<TreeNode*> s;
vector<TreeNode*> vec; // p和q的公共祖先
bool tag1 = false; // true:找到p
bool tag2 = false; // true:找到q
s.push(root);
TreeNode* lastRoot = root;
while (!s.empty()) // lastRoot(区分从左/右孩子返回)
{
root = s.top();
if (root == p) {
if(tag1 == false && tag2 == false)
vec.push_back(root);
tag1 = true;
}
else if (root == q) {
if (tag2 == false && tag1 == false)
vec.push_back(root);
tag2 = true;
}
if (!tag1 && !tag2)
vec.push_back(root); // 公共祖先入vector
// 找到p,q并且root在公共祖先数组中
if (tag1 && tag2 && find(vec.begin(), vec.end(), root) != vec.end())
return root;
// root的孩子节点还没访问
if (lastRoot != root->right)
{
if (lastRoot != root->left) {
if (root->left != nullptr) {
s.push(root->left);
continue;
}
}
if (root->right != nullptr) {
s.push(root->right);
continue;
}
}
// 孩子节点访问完,弹栈向上回溯
lastRoot = root;
s.pop();
}
return nullptr;
}

最近公共祖先 LCA 递归非递归的更多相关文章

  1. [程序员代码面试指南]二叉树问题-在二叉树中找到两个节点的最近公共祖先、[LeetCode]235. 二叉搜索树的最近公共祖先(BST)(非递归)

    题目 题解 法一: 按照递归的思维去想: 递归终止条件 递归 返回值 1 如果p.q都不在root为根节点的子树中,返回null 2 如果p.q其中之一在root为根节点的子树中,返回该节点 3 如果 ...

  2. Reverse Linked List 递归非递归实现

    单链表反转--递归非递归实现 Java接口: ListNode reverseList(ListNode head) 非递归的实现 有2种,参考 头结点插入法 就地反转 递归的实现 1) Divide ...

  3. Luogu 2245 星际导航(最小生成树,最近公共祖先LCA,并查集)

    Luogu 2245 星际导航(最小生成树,最近公共祖先LCA,并查集) Description sideman做好了回到Gliese 星球的硬件准备,但是sideman的导航系统还没有完全设计好.为 ...

  4. POJ 1470 Closest Common Ancestors(最近公共祖先 LCA)

    POJ 1470 Closest Common Ancestors(最近公共祖先 LCA) Description Write a program that takes as input a root ...

  5. POJ 1330 Nearest Common Ancestors / UVALive 2525 Nearest Common Ancestors (最近公共祖先LCA)

    POJ 1330 Nearest Common Ancestors / UVALive 2525 Nearest Common Ancestors (最近公共祖先LCA) Description A ...

  6. 【数据结构】——搜索二叉树的插入,查找和删除(递归&非递归)

    一.搜索二叉树的插入,查找,删除 简单说说搜索二叉树概念: 二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值 若它的右 ...

  7. [模板] 最近公共祖先/lca

    简介 最近公共祖先 \(lca(a,b)\) 指的是a到根的路径和b到n的路径的深度最大的公共点. 定理. 以 \(r\) 为根的树上的路径 \((a,b) = (r,a) + (r,b) - 2 * ...

  8. 【lhyaaa】最近公共祖先LCA——倍增!!!

    高级的算法——倍增!!! 根据LCA的定义,我们可以知道假如有两个节点x和y,则LCA(x,y)是 x 到根的路 径与 y 到根的路径的交汇点,同时也是 x 和 y 之间所有路径中深度最小的节 点,所 ...

  9. 【Leetcode】查找二叉树中任意结点的最近公共祖先(LCA问题)

    寻找最近公共祖先,示例如下: 1 /           \ 2           3 /    \        /    \ 4    5      6    7 /    \          ...

随机推荐

  1. Lexicographical Substring Search SPOJ - SUBLEX (后缀数组)

    Lexicographical Substrings Search \[ Time Limit: 149 ms \quad Memory Limit: 1572864 kB \] 题意 给出一个字符串 ...

  2. Apache ServiceComb Pack 微服务分布式数据最终一致性解决方案

    https://github.com/OpenSagas-csharp/servicecomb-pack-csharp Saga基本使用指南 使用前置条件说明 如果还有同学对Saga还不甚了解的同学, ...

  3. 关于单片机的RAM

    一块RAM 分为了 堆 和 栈   名词而已,知道就可以了, 各种内存溢出问题: 全局数组访问越界 出现的问题:直接重启,或者死机 解决办法 :  额,写好自己的程序吧!!!!!!! 函数的局部变量过 ...

  4. 使用 gitstats 来统计代码

    使用 gitstats 来统计代码 github地址如下 gitstats clone地址 git clone https://github.com/hoxu/gitstats && ...

  5. nginx 配置虚拟主机( 基于端口 )

    一.创建网站目录及文件: [root@localhost data]# tree /data /data └── wwwroot ├── www.1.com_8080 │   └── index.ht ...

  6. 第09组 Alpha冲刺(3/6)

    队名:观光队 组长博客 作业博客 组员实践情况 王耀鑫 过去两天完成了哪些任务 文字/口头描述 完成服务器连接数据库部分代码 展示GitHub当日代码/文档签入记录 接下来的计划 服务器网络请求,vu ...

  7. 通过shell脚本查看python版本并比较

    a.py import sys print(].split(])) test.sh #!/bin/sh zero= x=`python a.py` y="3.6" status=` ...

  8. 《Go语言实战》读书笔记

    <Go语言实战>中文版pdf 百度网盘: https://pan.baidu.com/s/1kr-gMzaPAn8BFZG0P24Oiw 提取码: r6rt 书籍源码:https://gi ...

  9. 安全漏洞XSS、CSRF、SQL注入以及DDOS攻击

    随着互联网的普及,网络安全变得越来越重要,程序员需要掌握最基本的web安全防范,下面列举一些常见的安全漏洞和对应的防御措施. 0x01: XSS漏洞 1.XSS简介 跨站脚本(cross site s ...

  10. canvas笔记备忘

    备忘 1. canvas标签的宽和高设置是标签属性设置, 不是 css 属性设置. 如果用 css 属性设置大小, canvas 会被拉伸. 标签属性例如: class, id, style, wid ...