题目:
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 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).”Given the following binary tree: root = [3,5,1,6,2,0,8,null,null,7,4]
_______3______ / \ ___5__ ___1__ / \ / \ 6 _2 0 8 / \ 7 4
Example 1:
Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1 Output: 3 Explanation: The LCA of of nodes 5 and 1 is 3.
Example 2:
Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4 Output: 5 Explanation: The LCA of nodes 5 and 4 is 5, since a node can be a descendant of itself according to the LCA definition.
Note:
All of the nodes’ values will be unique.
p and q are different and both values will exist in the binary tree.
解释:
1.是一个普通的二叉树,不是BST,所以不能根据根节点大于其中一个结点并且小于另一个结点来判断
2.没有指向父节点的指针,所以不能直接用“寻找两个链表的第一个公共结点”来解决
3.不断遍历并判断,如果某个结点的两个子树分别包含这两个结点,但是它的某个子结点中不同时包含这两个结点,那么这个结点就是公共结点,这个方法会重复计算(大神的解法)
4.先用两个链表存储从根节点到两个子节点的路径(回溯法),再判断路径的公共结点(这样的两个链表是从公共结点开始分叉,而不是先分叉再融合,所以判断的时候不需要双指针来回走,更加简单)
问题:二叉树结点的值有没有可能是一样的?
第一种解法,python代码:
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution(object):
def lowestCommonAncestor(self, root, p, q):
"""
:type root: TreeNode
:type p: TreeNode
:type q: TreeNode
:rtype: TreeNode
"""
if root in (None,p,q):
return root
left=self.lowestCommonAncestor(root.left,p,q)
right=self.lowestCommonAncestor(root.right,p,q)
return root if left and right else left or right
c++代码,注意 left
和right
用NULL
初始化:
/**
* 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) {
vector<TreeNode*> tmp={NULL,p,q};
if (count(tmp.begin(),tmp.end(),root))
return root;
TreeNode* left=NULL;
TreeNode* right=NULL;
if (root->left)
left=lowestCommonAncestor(root->left,p,q);
if(root->right)
right=lowestCommonAncestor(root->right,p,q);
if (left&&right)
return root;
else if (left)
return left;
else
return right;
}
};
第二种解法,由于回溯的最终结果并不是返回路径,或者把路径保存在某个结果中,所以不能用path+[new_val]的方式回溯,而应该用push()
+pop()
的方式,再说,在别的语言里面也没有这种直接相加的办法,只有python有,用别的语言实现回溯都是push()
+pop()
。
python代码:
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution(object):
def lowestCommonAncestor(self, root, p, q):
"""
:type root: TreeNode
:type p: TreeNode
:type q: TreeNode
:rtype: TreeNode
"""
#不需要重新定义链表的数据结构,用一个list存储TreeNode即可
def getPath(root,node,path):
if root==None:
return None
path.append(root)
if root==node:
return True
found=False
if not found and root.left:
found= getPath(root.left,node,path)
if not found and root.right:
found=getPath(root.right,node,path)
if not found:
path.pop()
return found
def getLastCommonNode(path1,path2):
pLast=None
i=0
while i<min(len(path1),len(path2)):
if path1[i]==path2[i]:
pLast=path1[i]
i+=1
else:
break
return pLast
if not root or not p or not q:
return None
#由于不是只有一个path,所以不能用self.path,要把path作为一个参数传入函数
path1=[]
path2=[]
getPath(root,p,path1)
getPath(root,q,path2)
return getLastCommonNode(path1,path2)
c++代码,学习一下用cpp实现回溯:
/**
* 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) {
vector<TreeNode*>path1,path2;
bool bool1=getPath(root,path1,p);
bool bool2=getPath(root,path2,q);
TreeNode*lp=NULL;
int i=0;
while(i<min(path1.size(),path2.size()))
{
if (path1[i]==path2[i])
{
lp=path1[i];
i+=1;
}
else
break;
}
return lp;
}
bool getPath(TreeNode*root,vector<TreeNode*>& path,TreeNode* target)
{
if(!root)
return NULL;
path.push_back(root);
bool found=false;
if (root==target)
return true;
if (!found &&root->left)
found=getPath(root->left,path,target);
if(!found &&root->right)
found=getPath(root->right,path,target);
if (!found)
path.pop_back();
return found;
}
};
总结:
python中,return a or b
的意思是,当a不为空则返回a,否则返回b。