C++面试题(55)------二叉树的最近公共祖先

  • 操作系统:ubuntu22.04
  • IDE:Visual Studio Code
  • 编程语言:C++11

题目描述

给定一个二叉树(不一定是二叉搜索树),和两个节点 p 和 q,请找出它们在这棵树中的最近公共祖先(LCA)。

定义:

最近公共祖先(LCA)是指在二叉树中,两个节点 p 和 q 向上回溯时最先交汇的那个节点。

解法思路:递归 + 回溯

这是一道典型的二叉树递归题,考察你对 DFS 与递归的理解。
🔍 核心思想:

我们从根节点开始递归查找:

  • 如果当前节点是 p 或 q,直接返回该节点;
  • 分别递归查找左子树和右子树;
  • 如果左右子树都找到了节点,则当前节点就是 LCA;
  • 如果只有一边找到了,则那一边继续向上返回找到的节点;
  • 如果两边都没找到,返回 nullptr。

假设如下二叉树:

        3
       / \
      5   1
     / \ / \
    6  2 0  8
      / \
     7   4

p = 5(节点值为 5)
q = 1(节点值为 1)

✅ 答案是:3(它们的最近公共祖先是根节点)

代码


#include <iostream>
#include <string>
using namespace std;

struct TreeNode {
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode( int x ) : val( x ), left( nullptr ), right( nullptr ) {}
};

class Solution {
public:
    TreeNode* lowestCommonAncestor( TreeNode* root, TreeNode* p, TreeNode* q )
    {
        if ( !root || root == p || root == q )
            return root;

        TreeNode* left  = lowestCommonAncestor( root->left, p, q );
        TreeNode* right = lowestCommonAncestor( root->right, p, q );

        // 如果左右子树都找到了,说明当前节点是 LCA
        if ( left && right )
            return root;

        // 否则返回找到的那个子树
        return left ? left : right;
    }
};

int main()
{
    // 构建如下结构的二叉树:
    //         3
    //        / \
    //       5   1
    //      / \ / \
    //     6  2 0  8
    //       / \
    //      7   4

    TreeNode* root           = new TreeNode( 3 );
    root->left               = new TreeNode( 5 );
    root->right              = new TreeNode( 1 );
    root->left->left         = new TreeNode( 6 );
    root->left->right        = new TreeNode( 2 );
    root->right->left        = new TreeNode( 0 );
    root->right->right       = new TreeNode( 8 );
    root->left->right->left  = new TreeNode( 7 );
    root->left->right->right = new TreeNode( 4 );

    // 测试用例 1: p = 5(节点值为5), q = 1(节点值为1)
    TreeNode* p = root->left;   // 节点 5
    TreeNode* q = root->right;  // 节点 1

    Solution sol;
    TreeNode* lca = sol.lowestCommonAncestor( root, p, q );
    cout << "LCA of 5 and 1 is: " << lca->val << endl;  // 应该输出 3

    // 测试用例 2: p = 5, q = 4
    p = root->left;                // 节点 5
    q = root->left->right->right;  // 节点 4

    lca = sol.lowestCommonAncestor( root, p, q );
    cout << "LCA of 5 and 4 is: " << lca->val << endl;  // 应该输出 5

    // 测试用例 3: p = 7, q = 8
    p = root->left->right->left;  // 节点 7
    q = root->right->right;       // 节点 8

    lca = sol.lowestCommonAncestor( root, p, q );
    cout << "LCA of 7 and 8 is: " << lca->val << endl;  // 应该输出 3

    // 释放内存(可选)
    // 注意:实际项目中应使用递归方式释放整个树
    // 这里为了简单起见省略 delete 操作

    return 0;
}

运行结果

LCA of 5 and 1 is: 3
LCA of 5 and 4 is: 5
LCA of 7 and 8 is: 3
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

村北头的码农

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值