二叉树的最近公共祖先
1. 题意
该题为 leetcode 的 236 题
题意:
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为: “对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出:3
解释:节点 5 和节点 1 的最近公共祖先是节点 3 。
输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
输出:5
解释:节点 5 和节点 4 的最近公共祖先是节点 5 。因为根据定义最近公共祖先节点可以为节点本身。
2. 思路
作为一个公共父节点,它应该有以下特征:
- 如果该节点既不是 p p p 又不是 q q q,那么 p p p q q q 一定分别存在于 该节点的左右子树
- 如果该节点是其中一个节点 p p p 或 q q q,那么,该节点的左子树或右子树必然包含 q q q 或 p p p
在官方题解中:
使用
l
s
o
n
lson
lson 表示左子树包含
p
p
p 或
q
q
q, 使用
r
s
o
n
rson
rson 表示右子树包含
p
p
p 或
q
q
q
而根据以上的特征,父节点所满足的条件应该是:
(
l
s
o
n
&
&
r
s
o
n
)
∣
∣
(
(
r
o
o
t
.
v
a
l
=
=
q
.
v
a
l
∣
∣
r
o
o
t
.
v
a
l
=
=
p
.
v
a
l
)
&
&
(
l
s
o
n
∣
∣
r
s
o
n
)
)
(lson \&\& rson) ||((root.val == q.val || root.val == p.val) \&\& (lson || rson))
(lson&&rson)∣∣((root.val==q.val∣∣root.val==p.val)&&(lson∣∣rson))
3. 实现
正是基于以上特征,采用递归的方式进行深度优先搜索
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
private TreeNode ans;
public Solution() {
this.ans = null;
}
private boolean dfs(TreeNode root, TreeNode p, TreeNode q) {
if (root == null)
return false;
//左右子树是否包含 p q 节点
boolean lson = dfs(root.left,p,q);
boolean rson = dfs(root.right,p,q);
if ((lson && rson) || ((root.val == q.val) || (root.val == p.val)) && (lson || rson))
this.ans = root;
return lson || rson || root.val == q.val || root.val == p.val;
}
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
this.dfs(root,p,q);
return this.ans;
}
}