235.二叉搜索树的最近公共祖先
给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,null,3,5]
这个题如果不加上二叉搜索树难度会更大一些。但是既然给了,就应该利用左<中<右的特性。通过寻找目标点,来得到根节点到目标节点的路径。得到两个点的路径后,从路径的开始进行对比,找到最深入的一个祖先。
当然,如果不加上二叉搜索树,就可以利用后序遍历的特性来找到最近的公共祖先。
代码里,学到了新的zip函数。能够将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。 在代码中体现的是:能够在两条路径中同时同步开始搜索。如路径为(6, 2, 4, 3)与(6, 2, 0),则从6开始依次对比两个路径的点。
代码:
class Solution(object):
def lowestCommonAncestor(self, root, p, q):
"""
:type root: TreeNode
:type p: TreeNode
:type q: TreeNode
:rtype: TreeNode
"""
def getPath(root, target):
path = []
node = root
while node != target:
path.append(node)
if target.val < node.val:
node = node.left
else:
node = node.right
path.append(node) # 将target本身也加入路径中,因为有可能祖先为自身
return path
path_p = getPath(root, p)
path_q = getPath(root, q)
ancestor = None
for u, v in zip(path_p, path_q): # 持续向前找,找到最近的
if u == v:
ancestor = u # 若找到更深入的,就更新
else:
break # 跳出当前循环
return ancestor
- 二叉树的最近公共祖先
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
这个题就是普通的二叉树了,不能使用特性。但可以利用后序遍历的特性。后序遍历最好用迭代的,可以看这一篇。当后序遍历到目标点时,退出函数,返回栈。然后再将该目标点加入栈内,最后进行对比,找出公共祖先。
class Solution(object):
def lowestCommonAncestor(self, root, p, q):
"""
:type root: TreeNode
:type p: TreeNode
:type q: TreeNode
:rtype: TreeNode
"""
def getPostOrderPath(root, target): # 后序遍历
stack = []
prev = None
while root or stack:
while root:
if root != target: # 如果不等于目标值
stack.append(root) # 进栈
root = root.left # 左移
else: # 若等于目标值
return stack # 返回栈中所有元素
root = stack.pop()
if root.right and root.right != prev:
if root != target:
stack.append(root)
root = root.right
else: # 如果等于目标值
return stack # 返回栈中所有元素
else:
prev = root
root = None
# 以上都为后序遍历的改写,下面的则与搜索二叉树的寻找代码一致
path_p = getPostOrderPath(root, p)
path_p.append(p)
path_q = getPostOrderPath(root, q)
path_q.append(q)
ancestor = None
for u, v in zip(path_p, path_q):
if u == v:
ancestor = u
else:
break
return ancestor