Problem: 236. 二叉树的最近公共祖先
思路
你选用何种方法解题? 深度遍历
解题过程
这些方法具体怎么运用?
分别找到从根节点到两个目标节点的路径 比较两条路径,找到最后一个相同的节点 这个节点就是两个目标节点的最近公共祖先
/**
* Definition for a binary tree node.
* class TreeNode {
* val: number
* left: TreeNode | null
* right: TreeNode | null
* constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
* }
*/
// 深度优先搜索函数,用于查找从当前节点到目标节点的路径
function dfs(cur: TreeNode | null, t: TreeNode | null, path: TreeNode[]): boolean {
// 如果当前节点为空,返回false表示未找到目标
if (!cur) return false;
// 将当前节点加入路径
path.push(cur);
// 检查是否找到目标节点,或者在左子树/右子树中找到目标节点
if (cur === t || dfs(cur.left, t, path) || dfs(cur.right, t, path)) {
// 如果找到目标节点,返回true
return true;
} else {
// 如果当前分支没有找到目标节点,从路径中移除当前节点(回溯)
path.pop();
return false;
}
}
// 主函数:找到两个节点的最近公共祖先
function lowestCommonAncestor(root: TreeNode | null, p: TreeNode | null, q: TreeNode | null): TreeNode | null {
// 创建两个数组用于存储从根节点到p和q的路径
const a = [], b = [];
// 分别查找从根节点到p和q的路径
dfs(root, p, a);
dfs(root, q, b);
// 初始化结果为null
let ans = null;
// 遍历两条路径,找到最后一个相同的节点
for (let i = 0; i < Math.min(a.length, b.length) && a[i] === b[i]; i++) {
ans = a[i];
}
// 返回最近公共祖先
return ans;
}
示例1:查找节点5和节点1的最近公共祖先
-
查找路径到节点5:
- 从根节点3开始:
[3] - 访问左子节点5:
[3, 5] - 找到目标节点5,返回路径
[3, 5]
- 从根节点3开始:
-
查找路径到节点1:
- 从根节点3开始:
[3] - 访问右子节点1:
[3, 1] - 找到目标节点1,返回路径
[3, 1]
- 从根节点3开始:
-
比较路径:
- 路径1:
[3, 5] - 路径2:
[3, 1] - 公共部分:
[3] - 最近公共祖先: 节点3
- 路径1:
示例2:查找节点6和节点4的最近公共祖先
-
查找路径到节点6:
- 从根节点3开始:
[3] - 访问左子节点5:
[3, 5] - 访问左子节点6:
[3, 5, 6] - 找到目标节点6,返回路径
[3, 5, 6]
- 从根节点3开始:
-
查找路径到节点4:
- 从根节点3开始:
[3] - 访问左子节点5:
[3, 5] - 访问右子节点2:
[3, 5, 2] - 访问右子节点4:
[3, 5, 2, 4] - 找到目标节点4,返回路径
[3, 5, 2, 4]
- 从根节点3开始:
-
比较路径:
- 路径1:
[3, 5, 6] - 路径2:
[3, 5, 2, 4] - 公共部分:
[3, 5] - 最近公共祖先: 节点5
- 路径1: