【力扣hot100】二叉树的最近公共祖先 - DFS

30 阅读2分钟

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的最近公共祖先

  1. 查找路径到节点5

    • 从根节点3开始:[3]
    • 访问左子节点5:[3, 5]
    • 找到目标节点5,返回路径 [3, 5]
  2. 查找路径到节点1

    • 从根节点3开始:[3]
    • 访问右子节点1:[3, 1]
    • 找到目标节点1,返回路径 [3, 1]
  3. 比较路径

    • 路径1: [3, 5]
    • 路径2: [3, 1]
    • 公共部分: [3]
    • 最近公共祖先: 节点3

示例2:查找节点6和节点4的最近公共祖先

  1. 查找路径到节点6

    • 从根节点3开始:[3]
    • 访问左子节点5:[3, 5]
    • 访问左子节点6:[3, 5, 6]
    • 找到目标节点6,返回路径 [3, 5, 6]
  2. 查找路径到节点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