package com.myproject.demo.算法;
/**
* 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
* <p>
* 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
* <p>
* 例如,给定如下二叉树: root = [3,5,1,6,2,0,8,null,null,7,4]
* <p>
* <p>
* <p>
* 示例 1:
* <p>
* 输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
* 输出: 3
* 解释: 节点 5 和节点 1 的最近公共祖先是节点 3。
* <p>
* 示例 2:
* <p>
* 输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
* 输出: 5
* 解释: 节点 5 和节点 4 的最近公共祖先是节点 5。因为根据定义最近公共祖先节点可以为节点本身。
* <p>
* 来源:力扣(LeetCode)
* 链接:https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree
* 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
*
* @author yuJie
* @since 2020/5/7
*/
public class 二叉树的最近公共祖先 {
private TreeNode result = null;
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) {
val = x;
}
}
/**
* 方法一:递归
* 思路:首先他的祖先可能有多个,而我们需要找的是最近最深的一个。
* 判断一个节点root是不是他们p,q的公共祖先三种情况:
* 1.root的左右子树包含了p,q
* 2.root就是p,他的左右子树有一个包含了q
* 3.root就是q,他的左右子树有一个包含了p
* 现在可以判断一个节点是不是他的公共祖先,那怎么找最深的一个呢?
* 使用递归。遍历所有的节点,因为递归是深度优先搜索。他执行顺序是先执行最底层的节点
* 如果最底层的节点返回了true。那就是最深了所以代码如下
*
* @param root
* @param p
* @param q
* @return
*/
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
recurse(root, p, q);
return result;
}
public Boolean recurse(TreeNode root, TreeNode p, TreeNode q) {
if (root == null || result != null) {
return false;
}
int left = recurse(root.left, p, q) ? 1 : 0;
int right = recurse(root.right, p, q) ? 1 : 0;
int mid = root == p || root == q ? 1 : 0;
//以当前节点找到了p,q就是结果,这边有个问题,当找到了最近祖先时候,还会继续执行没有中断可以增加个result != null终止执行
if ((left + right + mid) >= 2) {
result = root;
}
//当前节点不是结果,就要返回当前节点有没有找到p,q
return (left + right + mid) > 0;
}
}
还有别的方法,今明两天更新,上班干活了