#|二叉树中两个节点的最近公共祖先(leetcode)
leetcode题目地址 https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree/#/description
二叉树构造
TreeNode* t1 = new TreeNode(3);
TreeNode* t2 = new TreeNode(5);
TreeNode* t3 = new TreeNode(1);
TreeNode* t4 = new TreeNode(6);
TreeNode* t5 = new TreeNode(2);
TreeNode* t6 = new TreeNode(0);
TreeNode* t7 = new TreeNode(8);
TreeNode* t8 = new TreeNode(7);
TreeNode* t9 = new TreeNode(4);
t1->left = t2;
t1->right = t3;
t2->left = t4;
t2->right = t5;
t3->left = t6;
t3->right = t7;
t5->left = t8;
t5->right = t9;
TreeNode* root = t1;
/*
_______3______
/\
___5_____1__
/\/\
6_208
/\
74
*/
AC1 使用dfs得到根结点到某个结点的路径,然后比对路径就可以得到最近的公共祖先
/**
* Definition for a binary tree node.
* struct TreeNode {
*int val;
*TreeNode *left;
*TreeNode *right;
*TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:vector fa1;
vector fa2;
void dfs(vector &fa, TreeNode* root, TreeNode* p, TreeNode* q)
{
if (root == NULL)
return ;
if (root == p){
fa1 = fa;
}
if (root == q){
fa2 = fa;
}if (root->left != NULL){
fa.push_back(root->left);
dfs(fa,root->left, p,q);
fa.pop_back();
}
if (root->right != NULL)
{
fa.push_back(root->right);
dfs(fa, root->right, p,q);
fa.pop_back();
}
}TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
vector fa;
fa.push_back(root);
dfs(fa, root, p,q);
vector::iterator it1 = fa1.begin();
vector::iterator it2 = fa2.begin();
TreeNode* ans = NULL;
;
while (it1 != fa1.end() && it2 != fa2.end())
{
if (*it1 == *it2)
{
ans = *it1;
it1++;
it2++;
}
else{
break;
}
}return ans;
}
};
ac2 参考思路:
http://blog.csdn.net/shixiaoguo90/article/details/23824325
遍历二叉树时,只有先访问给定两节点A、B后,才可能确定其最近共同父节点C,因而采用后序遍历。
可以统计任一节点的左右子树“是否包含A、B中的某一个”(也可以直接统计“包含了几个A、B”)。当后序遍历访问到某个节点D时,可得到三条信息:(1)节点D是否是A、B两节点之一、(2)其左子树是否包含A、B两节点之一、(3)其右子树是否包含A、B两节点之一。当三条信息中有两个为真时,就可以确定节点D的父节点(或节点D,如果允许一个节点是自身的父节点的话)就是节点A、B的最近共同父节点。另外,找到最近共同父节点C后应停止遍历其它节点。
【#|二叉树中两个节点的最近公共祖先(leetcode)】原文的代码似乎不符合,我重新改写了一下代码,ac如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
*int val;
*TreeNode *left;
*TreeNode *right;
*TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:bool lca(TreeNode *root, TreeNode* va, TreeNode* vb, TreeNode *&result)
{
// left/right 左/右子树是否含有要判断的两节点之一
bool left = false, right = false;
if (!result && root->left != NULL)
left = lca(root->left,va,vb,result);
if (!result && root->right != NULL)
right = lca(root->right,va,vb,result);
// mid 当前节点是否是要判断的两节点之一
bool mid = false;
if (root == va || root == vb)
mid = true;
if (!result && int(left + right + mid) == 2)
{
result = root;
// root就是后序遍历(左,右,根),当前遍历的那个节点
}
return left | mid | right ;
}TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q)
{
if (root == NULL)
return NULL;
TreeNode *result = NULL;
lca(root, p, q,result);
return result;
}
};
推荐阅读
- java中如何实现重建二叉树
- 刘婵为何不娶关羽的女儿为妻子,而为何要娶张飞的两个女儿
- 说睡
- 二叉树路径节点关键值和等于目标值(LeetCode--112&LeetCode--113)
- 有人与我谈格局
- ||11|2019年9月9日
- 活的教导7:两个阶段
- 两个人在一起,最怕将就。
- 两个心得
- 两个一年级