二叉树之最近公共祖先LCA
Posted 叶孤城_
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二叉树之最近公共祖先LCA相关的知识,希望对你有一定的参考价值。
问题描述
给你一个指向二叉树的根结点的指针,和两个指向二叉树中不同结点的指针 p 和 q,返回指向 p 和 q 的最近公共祖先的指针。(二叉树中的结点值唯一)
概念介绍
最近公共祖先:
According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself).”
简单来说就是拥有 p 和 q 作为后代(允许一个结点作为自己的后代)的所有结点中层数最大的那个结点。
LCA主要是用来处理当两个点仅有唯一一条确定的最短路径时的路径。
算法
一、暴力解法
递归地看,对每一个传入的结点参数 root:
1 . 如果 root 的值等于 p 或 q 中的一个,那么 root 为最近公共祖先(因为是从上往下查找)
2 . 如果左子树同时拥有 p 和 q,或者右子树同时拥有 p 和 q,那么递归处理左或右子树
3 . 如果左右子树各拥有 p,q 中的一个,那么 root 为最近公共祖先
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
class Solution {
public:
int findNode(TreeNode* root, int target){
if(!root) return 0;
if(root->val==target) return 1;
else return findNode(root->left, target) | findNode(root->right, target);
}
TreeNode* findLowest(TreeNode* root, int p, int q){
if(!root) return nullptr;
if(root->val==p || root->val==q){
return root;
}
int lp,lq,rp,rq;
lp=findNode(root->left, p);
lq=findNode(root->left, q);
rp=findNode(root->right, p);
rq=findNode(root->right, q);
if(lp && lq){
return findLowest(root->left, p, q);
}else if(rp && rq){
return findLowest(root->right, p, q);
}else{
return root;
}
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
return findLowest(root, p->val, q->val);
}
};
这个方法是第一时间顺着题目意思想出来的方法,可以明显看出来时间复杂度非常高,因为在每一个结点,都要搜索一遍其左右子树。
二、递归解法
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if(!root) return nullptr;
if(root->val==p->val || root->val==q->val){
return root;
}
TreeNode* left=lowestCommonAncestor(root->left, p, q);
TreeNode* right=lowestCommonAncestor(root->right, p, q);
if(!left){
return right;
}else if(!right){
return left;
}else{
return root;
}
}
};
三、区别
两种解法都是自顶向下查找,而其区别在于:
- 一中,findLowest() 函数每次递归必须确保其 root 参数中含有 p 和 q,实质上是找出了自顶向下对 LCA 的搜索路径
- 二中,lowestCommonAncestor() 函数则是 dfs 遍历整棵树,每一级在返回的时候也携带了搜索结点的结果信息,通过判断找出 LCA,其时间复杂度为 O(N)
以上是关于二叉树之最近公共祖先LCA的主要内容,如果未能解决你的问题,请参考以下文章