- 操作系统: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