题目
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
一、代码实现
go
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
if root == nil || root == p || root == q {
return root
}
left := lowestCommonAncestor(root.Left, p, q)
right := lowestCommonAncestor(root.Right, p, q)
if left != nil && right != nil {
return root
}
if left != nil {
return left
}
return right
}
二、算法分析
1. 核心思路
- 后序遍历:自底向上查找目标节点,通过递归返回值传递状态
- 状态判断:当某个节点的左右子树分别包含目标节点时,即为LCA
2. 关键步骤
- 递归终止:遇到空节点或目标节点立即返回
- 子树搜索:分别在左右子树中查找目标节点
- 结果合并 :
- 左右子树均有返回值 → 当前节点为LCA
- 仅单侧有返回值 → 继续向上传递该结果
3. 复杂度
指标 | 值 | 说明 |
---|---|---|
时间复杂度 | O(n) | 每个节点遍历一次 |
空间复杂度 | O(h) | 递归栈空间,h为树的高度 |
三、图解示例

四、边界条件与扩展
1. 特殊场景验证
- 节点为根节点:返回根节点
- 节点互为祖先:返回层级更高的节点
- 节点不在树中:返回null(需预先验证)
2. 多语言实现
python
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
if not root or root == p or root == q:
return root
left = self.lowestCommonAncestor(root.left, p, q)
right = self.lowestCommonAncestor(root.right, p, q)
return root if left and right else left or right
java
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == null || root == p || root == q) return root;
TreeNode left = lowestCommonAncestor(root.left, p, q);
TreeNode right = lowestCommonAncestor(root.right, p, q);
return left != null && right != null ? root : left != null ? left : right;
}
}
五、总结与扩展
1. 核心创新点
- 状态传递:利用递归返回值携带子树搜索信息
- 短路优化:发现目标节点后立即停止子树搜索
2. 扩展应用
- 多节点LCA:扩展算法处理多个目标节点
- 带父指针树:使用哈希表存储访问路径
- 频繁查询优化:结合RMQ算法预处理
3. 工程优化
- 迭代实现:用栈模拟后序遍历
- 路径记录:显式存储节点访问路径
- 输入验证:增加节点存在性检查