# 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':
"""
查找二叉搜索树 (BST) 中两个给定节点 p 和 q 的最近公共祖先 (LCA)。
利用 BST 的性质:左子树节点 < 根节点 < 右子树节点。
Args:
root: 二叉搜索树的根节点。
p: 树中的一个节点。
q: 树中的另一个节点。
Returns:
节点 p 和 q 的最近公共祖先节点。
"""
# 从根节点开始遍历
cur = root
# 循环遍历树,直到找到 LCA
# 在 BST 中,LCA 是第一个值位于 p 和 q 之间的节点(包括 p 或 q 本身)
while cur:
# 情况 1: 如果 p 和 q 的值都小于当前节点 cur 的值
if p.val < cur.val and q.val < cur.val:
# 这意味着 p 和 q 肯定都在 cur 的左子树中
# 因此,LCA 也必定在左子树中,将 cur 移动到左子节点
cur = cur.left
# 情况 2: 如果 p 和 q 的值都大于当前节点 cur 的值
elif p.val > cur.val and q.val > cur.val:
# 这意味着 p 和 q 肯定都在 cur 的右子树中
# 因此,LCA 也必定在右子树中,将 cur 移动到右子节点
cur = cur.right
# 情况 3: 如果不满足上述两种情况,则意味着:
# a) p 和 q 分别位于 cur 的左右子树中。
# b) 或者 p 或 q 其中一个等于 cur。
# 在这两种子情况中,当前的 cur 节点就是 p 和 q 的最近公共祖先 (LCA)。
# 因为它是第一个使得 p 和 q 不再位于同一侧子树的祖先节点。
else:
# 找到 LCA,返回当前节点 cur
return cur
# 如果 p 和 q 保证存在于树中,理论上循环总会在找到 LCA 时通过 return cur 结束。
# 如果需要处理 p 或 q 可能不在树中的情况,这里可能需要返回 None 或其他指示。
# 但根据 LeetCode 题目通常的假设,p 和 q 存在于树中,所以总能找到 LCA。
# return None # 通常不需要