您的位置:首页 > 其它

[leetcode] 236. Lowest Common Ancestor of a Binary Tree 解题报告

2016-01-12 12:03 459 查看
题目链接:https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree/

Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree.

According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined
between two nodes v and w as the lowest node in T that has both v and w as descendants (where we allow a node to be a descendant of itself).”
_______3______
/              \
___5__          ___1__
/      \        /      \
6      _2       0       8
/  \
7   4


For example, the lowest common ancestor (LCA) of nodes
5
and
1
is
3
.
Another example is LCA of nodes
5
and
4
is
5
,
since a node can be a descendant of itself according to the LCA definition.

思路:找两个结点的最低公共祖先,而且树不是二叉搜索树,可以将问题转化为找两个链表的最长公共结点问题。
即找出到这两个结点的两条路径,保存路径上的结点,然后看最远哪个一样即可。举个栗子:

     _______3______
/              \
___5__          ___1__
/      \        /      \
6      _2       0       8
/  \
7   4


找5和4的公共最低公共祖先,我们先找出了到这两个结点的路径,即:

3->5

3->5->2->4

然后可以看出这两个链表的最长公共结点是5,因此5即是他们的最低公共祖先。

代码如下:

/**
* 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:
//在这里如果tem用值传递内存居然会爆掉
void search(TreeNode* root, vector<TreeNode*>& tem, TreeNode* p, TreeNode* q)
{
if(!root || list.size() == 2) return;
tem.push_back(root);
if(root == p || root == q)
list.push_back(tem);
search(root->left, tem, p, q);
search(root->right, tem, p, q);
tem.pop_back();//回溯
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if(!root || !p || !q) return NULL;
vector<TreeNode*> tem;
search(root, tem, p, q);//找出两个包含这两个结点的路径
int len1 = list[0].size(), len2 = list[1].size();
for(int i = 1; i< len1 && i < len2; i++)
{
if(list[0][i] != list[1][i])//当前结点不一样,说明上一个结点就是共同结点
return list[0][i-1];
//到达一个链表的尽头并且仍然相等,说明这个链表最后一个结点就是他们公共结点
if(i == len1-1 || i == len2-1)
return list[0][i];
}
return list[0][0];
}
private:
vector<vector<TreeNode*>> list;
};


写完之后看discus发现一种极其巧妙的方法,不得不为作者的想法赞叹。他的做法是搜索根的左右子树。

如果在左右子树中碰到了要搜索的结点,就返回那个结点,否则就递归往下搜索直到空结点。

如果其左右子树返回的都不为空,则说明两结点在此结点的两边,那么当前结点就是最低的公共祖先了。

如果其中一个结点返回的是空结点,那么另外一个返回的结点就是他们的最低公共祖先了。

举个栗子:

     _______3______
/              \
___5__          ___1__
/      \        /      \
6      _2       0       8
/  \
7   4

我们要找的两个结点分别是6和4。

1.搜索3的左右子树,右子树返回为空,左子树递归调用5

2.5再搜索其左右子树,左子树会返回6,右子树会返回4,这样5的左右子树都返回了一个非空值,5就是最低公共祖先了,将5结点返回上一层递归

3.在第一层递归3调用左右子树的时候,左子树就会返回5,右子树返回为空,这样就可以将5结点即递归调用左子树返回的结果返回就可以了

具体看代码:

/**
* 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:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if(!root || !p || !q) return NULL;
if(root == p || root == q)//如果找到了一个结点就返回
return root;
TreeNode* left = lowestCommonAncestor(root->left, p, q);
TreeNode* right = lowestCommonAncestor(root->right, p, q);
if(left && right)//左右子树各自找到了一个结点,说明当前结点就是最低公共祖先
return root;
return left?left:right;//如果其中一个返回为空,则另外一个返回的就是最低公共祖先
}
};


此方法参考:https://leetcode.com/discuss/62520/short-and-clean-c-solution
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: