给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
例如,给定如下二叉树: root = [3,5,1,6,2,0,8,null,null,7,4]
示例 1:
输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出: 3
解释: 节点 5 和节点 1 的最近公共祖先是节点 3。
输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
输出: 5
解释: 节点 5 和节点 4 的最近公共祖先是节点 5。因为根据定义最近公共祖先节点可以为节点本身。
分析:
有三种情况,p,q 都在左子树或右子树,p,q分别在左子树和右子树。
用到了分治法的思想,若是对于一个树结点,在左子树中找到了A,在右子树中找到了B,那说明此结点是公共节点。
class Solution(object):
def lowestCommonAncestor(self, root, p, q):
if root is None: return None
# root为p或者root为q,说明找到了p和q其中一个
if (root is p) or (root is q): return root
# 递归调用当前节点的左子树
left = self.lowestCommonAncestor(root.left,p,q)
# 递归调用当前节点的右子树
right = self.lowestCommonAncestor(root.right,p,q)
# 若左子树找到了p,右子树找到了q,说明此时的root就是公共祖先
if left and right: return root
# 若左子树是none,右子树不是,说明右子树找到了A或B
if not left: return right
# # 若右子树是none,左子树不是,说明左子树找到了A或B
if not right:return left
# 如果左边,右边都没找到呢?
参考:https://blog.csdn.net/wenqiwenqi123/article/details/79952043
这道题根本不会(????)以下是非递归版本:(谁能想到呢?)
首先说明:这个ppt是错误的,所以以下我照这个思路写的代码就是错的。
比如说p=5,q=1。那么先序遍历的结果(图里这个树)是3 5 6 2 7 4 1 0 8。
这个思路的答案是最后一个相同节点,那么是5,但是答案是3!!!
非递归版本——代码:
class Solution(object):
def lowestCommonAncestor(self, root, p, q):
"""
:type root: TreeNode
:type p: TreeNode
:type q: TreeNode
:rtype: TreeNode
"""
p_path, p_result = [], []
self.dfs(root, p, p_path, p_result)
q_path, q_result = [], []
self.dfs(root, q, q_path, q_result)
# 求最短的那dfs个路径
# print("p:",p_result)
# print("q:",q_result)
if len(p_result)<len(q_result):
path_len = len(p_result)
else:
path_len = len(q_result)
result = TreeNode(0)
for i in range(path_len):
if p_result[i].val == q_result[i].val:
result = p_result[i]
return result
def dfs(self,node,search,path,result):
# 先序遍历(深度优先遍历)
# node:正在遍历的结点;search:希望遍历到的结点
if node:
# 当node为空或已找到search结点,finish=1为找到
path.append(node)
while path:
node = path.pop()
result.append(node)
# print(result)
if node.val == search.val:
return result
if node.right:
path.append(node.right)
if node.left:
path.append(node.left)
return result