1.题目
这道题是2024-2-25的签到题,题目难度为中等。
考察知识点:二叉搜索树
题目链接:235. 二叉搜索树的最近公共祖先 - 力扣(LeetCode)
给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
2.思路
这道题和前段时间的一道签到题提醒类似,我也写了对那题的题解分析:
二叉树的最近公共祖先https://blog.csdn.net/hand2some2/article/details/136086720?spm=1001.2014.3001.5501 那道题的代码同样也可以解决这道题,为啥?二叉搜索树不就是特殊的二叉树嘛,只不过二叉搜索树有一个特点:它是比根节点值小的结点在根节点左边,比根节点值大的结点在根节点右边。因此如果我们还是用上面的那个题解的话,能解是能解,但是和我今天的这个思路相比它要慢一点。
我们根据二叉搜索树的特性可以将目标结点的值和结点的值进行比对,如果大于当前结点的值,则说明目标结点在当前节点的右子树上面;如果小于当前结点的值,则说明目标结点在当前结点的左子树上面;如果等于当前结点的值,说明当前结点就是目标结点。这样就可以省去遍历的大部分时间,遍历时间复杂度就变为了O(logn)。
我们可以在前面的遍历思路上再同时加一个路径列表用来保存目标结点的路径,这样我们就只需要比较两个路径中长度比较小的那个路径就行了,然后一一比对,因为公共祖先之前的路径它们是一模一样的。
3.代码
# 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':
# 定义两个遍历路径列表
find1,find2 = [],[]
# 定义遍历函数(二叉搜索树的)
def find(v,node,lis):
# 如果结点不为空
if node:
#将当前结点添加到遍历列表中
lis.append(node)
# 如果目标值等于当前结点值
if v == node.val:
return
# 如果目标值大于当前节点值
elif v > node.val:
# 遍历右子结点
find(v,node.right,lis)
# 如果目标值小于当前节点值
else:
# 遍历左子结点
find(v,node.left,lis)
# 遍历两个目标结点
find(p.val,root,find1)
find(q.val,root,find2)
# 最终结果
rst = None
# 两个遍历列表最小的长度
length = min(len(find1),len(find2))
# 一一比对
for i in range(length):
if find1[i] == find2[i]:
rst = find1[i]
# 返回最近公共祖先
return rst