给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,null,3,5]
输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
输出: 6
解释: 节点 2 和节点 8 的最近公共祖先是 6。
输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4
输出: 2
解释: 节点 2 和节点 4 的最近公共祖先是 2, 因为根据定义最近公共祖先节点可以为节点本身。
提示:
所有节点的值都是唯一的。
p、q 为不同节点且均存在于给定的二叉搜索树中。
代码如下:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
# 寻找p和q节点的父节点,如果2者其当前父节点相同或者其中一个的父节点等同于另一个节点,则表示找到;
# 如果当前父节点不相同,则继续找当前父节点的父节点,直到找到为止
p_father = []
q_father = []
def findp(r):
if r.val == p.val:
p_father.append(r)
return
elif r.val > p.val:
p_father.append(r)
findp(r.left)
else:
p_father.append(r)
findp(r.right)
def findq(r):
if r.val == q.val:
q_father.append(r)
return
elif r.val > q.val:
q_father.append(r)
findq(r.left)
else:
q_father.append(r)
findq(r.right)
findp(root)
findq(root)
result = root
for i in range(min(len(q_father),len(p_father))):
if q_father[i] == p_father[i]:
result = q_father[i]
continue
else:
break
return result
本题需要寻找的是某2个节点的公共父节点(该父节点也可能是节点本身),所以本题的解题思路为找出p,q
这2个节点的所有父节点,且包含有p,q
节点本身。
寻找p
或q
所有父节点思路为:从二叉树搜索树的根开始往下找,记录下当前的节点作为其父节点,然后根据p,q
节点的值的大小判断其应该在哪一个分支,前往那个分支重复以上操作,直到找到p、q
节点为止。(因为题意保证p、q
节点一定在数中存在且唯一,所以找到该节点的父节点路径仅有1条)
然后根据找到p、q
的所有父节点的列表,开始从头寻找这2个列表的公共最大子列表,找到其公共最大子列表后,返回其最后一位节点即可。
例如:
p_father = [6节点,2节点]
q_father = [6节点,2节点,4节点]
则p、q
父节点列表中的最大公共子列表为[6节点、2节点]
,则p、q
的公共最近父节点为最大公共子列表的最后一项——2节点
。
又例如:
p_father = [6节点,2节点]
q_father = [6节点,8节点]
则p、q
父节点列表中的最大公共子列表为[6节点]
,则p、q
的公共最近父节点为6节点
。