[AcWing]88. 树中两个结点的最低公共祖先

给出一个二叉树,输入两个树节点,求它们的最低公共祖先。

一个树节点的祖先节点包括它本身。

注意:

  • 输入的二叉树不为空;
  • 输入的两个节点一定不为空,且是二叉树中的节点;

数据范围

树中节点数量 [0,500]

样例

1
2
3
4
5
6
7
8
9
10
二叉树[8, 12, 2, null, null, 6, 4, null, null, null, null]如下图所示:
8
/ \
12 2
/ \
6 4

1. 如果输入的树节点为2和12,则输出的最低公共祖先为树节点8。

2. 如果输入的树节点为2和6,则输出的最低公共祖先为树节点2。

算法思想

image-20230424221354590

  1. 如果pq分别存在于这棵子树的左右两边,返回这棵子树的根,它就是最低公共祖先。
  2. 否则,pq只可能全存在于这棵子树的左边、或者全存在于这棵子树的右边。
  3. 如果当前节点恰好是pq中的一个,那么它就是最低公共祖先。

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
// 由于题目说了,输入的树不为空,并且p、q是树中的元素
// 就是说一定能够找到树中两个节点的最低公共祖先
// 遇到叶子节点
if(!root) return NULL;

// 左边找一下、右边找一下,遇到p、q节点就保存
TreeNode * left = lowestCommonAncestor(root -> left, p, q);
TreeNode * right = lowestCommonAncestor(root -> right, p, q);

// 如果p、q分别存在于这棵子树的左右两边,返回这棵子树的根,它就是p、q的最低公共祖先
if(left && right) return root;

// 那么p、q只可能全存在于这棵子树的左边、或者全存在于这棵子树的右边
// 如果当前节点恰好是p或q中的一个,那么它就是最低公共祖先
if(root == p || root == q) return root;

// 如果最低公共祖先在左边,返回左边的最低公共祖先
// 如果最低公共祖先在右边,返回右边的最低公共祖先
if(left) return left;
return right;
}
};

时间复杂度

遍历整棵子树,时间复杂度O(n)