一:题意
给定一颗二叉树,两个节点p和q,求出节点p和节点q的最低公共祖先。
最先公共祖先的定义是: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)
如图所示:1和5的公共祖先是3, 0和4的公共祖先是3, 4和5的公共祖先是5。。。
二:思路
(1)如果这棵树是排序二叉树,则先序遍历,对于每一个根节点,如果满足根节点的值的大小在节点p和节点q的值之间,则这个根节点就是最低公共祖先。
(2)如果每个节点的定义中出现了指向父节点的指针,则从节点p和节点q出发,沿着父指针向根节点遍历,得到两个链表,从而变成求两个链表的第一个公共节点。
(3)如果是普通的二叉树,则可以从第二种情况中受到启发,也就是Path Sum中的思想,深度优先搜索这棵树,当一条路径的末尾是节点p或节点q时,记录下这条路径,然后最终获得两条路径分别是从根节点到节点p,或从根节点到节点q,再求两个链表中最后一个公共节点。
三:举例说明与代码实现
方法一:Path Sum 中的记录路径的思路
例1:如上图所示
p = 2, q = 8
则两条路径分别为[3,5,2], [3,1,8],此时两条路径的最后一个公共节点就是节点3
例二:
p = 4, q = 5
则两条路径分别为[3,5,2,4], [3,5],此时两条路径的最后一个公共节点就是节点5
python实现为:
def lowestCommonAncestor(self, root, p, q):
if not root or not p or not q: return None
def dfs(root, p, q, path):
path.append(root) # 返回的是节点
# print(path)
# if not root.left and not root.right: return
if path[-1] == p or path[-1] == q:
self.ans.append(path[:]) # 这里一定得切片
if root.left:
dfs(root.left, p, q, path)
if root.right:
dfs(root.right, p, q, path)
path.pop()
self.ans = []
dfs(root, p, q, []) # 获取了两条路径
leni = len(self.ans[0])
lenj = len(self.ans[1])
i = 0
res = 0
while i < min(leni,lenj):
if self.ans[0][i] == self.ans[1][i]: # 球最后一个公共节点
res = self.ans[0][i]
i += 1
return res
方法二:使用父指针
思路:遍历二叉树时记录下节点的父节点,当遍历到节点p或节点q时,可以回溯到他们的最低公共祖先.
算法步骤:
python:
# Stack for tree traversal
stack = [root]
# Dictionary for parent pointers
parent = {root: None}
# Iterate until we find both the nodes p and q
while p not in parent or q not in parent: # 记录父节点
node = stack.pop()
# While traversing the tree, keep saving the parent pointers.
if node.left: # 层次遍历
parent[node.left] = node # key=子节点,value=父节点
stack.append(node.left)
if node.right:
parent[node.right] = node
stack.append(node.right)
# 开始回溯找最低公共祖先
# Ancestors set() for node p.
ancestors = set()
# Process all ancestors for node p using parent pointers.
while p:
ancestors.add(p)
p = parent[p]
# The first ancestor of q which appears in
# p's ancestor set() is their lowest common ancestor.
while q not in ancestors:
q = parent[q]
return q