难度: Medium
Submission
运行时间: 40 ms
内存: 19.5 MB
# Definition for a binary tree node. # class TreeNode: # def __init__(self, x): # self.val = x # self.left = None # self.right = None class Solution: def inorderSuccessor(self, root: TreeNode, p: TreeNode) -> Optional[TreeNode]: if not p: return None if p.right: q = p.right while q.left: q = q.left return q if p.val == root.val: return None nodeStay = root nodeIter = root while nodeIter.val != p.val: if nodeIter.val < p.val: nodeIter = nodeIter.right else: nodeStay = nodeIter nodeIter = nodeIter.left # print(nodeStay.val, nodeIter.val, p.val) if nodeStay.val < p.val : return None else: return nodeStay
Explain
该题解的思路是利用二叉搜索树的性质,中序遍历的后继节点有以下两种情况: 1. 如果给定节点 p 有右子树,则其中序后继为右子树中的最左节点。 2. 如果给定节点 p 没有右子树,则从根节点开始遍历,记录最后一个值小于 p 的节点,即为 p 的中序后继。
时间复杂度: O(h),其中 h 为二叉搜索树的高度,平均情况下为 O(log(n))
空间复杂度: O(1)
```python # Definition for a binary tree node. # class TreeNode: # def __init__(self, x): # self.val = x # self.left = None # self.right = None class Solution: def inorderSuccessor(self, root: TreeNode, p: TreeNode) -> Optional[TreeNode]: if not p: return None # 如果给定节点 p 有右子树,则其中序后继为右子树中的最左节点 if p.right: q = p.right while q.left: q = q.left return q # 如果 p 是根节点,且没有右子树,则没有中序后继 if p.val == root.val: return None nodeStay = root # 记录最后一个值小于 p 的节点 nodeIter = root # 用于遍历二叉搜索树的指针 # 从根节点开始遍历,找到给定节点 p while nodeIter.val != p.val: if nodeIter.val < p.val: nodeIter = nodeIter.right else: nodeStay = nodeIter nodeIter = nodeIter.left # 如果 p 的值大于 nodeStay,说明 p 没有中序后继 if nodeStay.val < p.val: return None else: return nodeStay ```
Explore
这一结论基于二叉搜索树的中序遍历特性。在二叉搜索树中,中序遍历会按照节点值的升序进行。若节点 p 有右子树,按照中序遍历的规则,p 的后继节点是其右子树中最小的节点,即右子树中最左侧的节点。这是因为在中序遍历中,任何节点的右子树中的遍历开始于该右子树的最左侧节点。
这种选择是基于中序遍历的顺序和二叉搜索树的属性。在中序遍历中,如果节点 p 没有右子树,那么其后继节点是在遍历序列中首次出现大于 p 的节点的父节点,这个父节点的值必须是所有大于 p 值的节点中最小的,即最后一个在遍历到 p 之前被访问的节点。这是因为在向上回溯过程中,这是第一个因为左子树遍历完成而被访问的节点。
题解的处理方式在遇到值等于 p 的节点的情况下可能存在问题。如果二叉树中有多个节点的值等于 p,并且这些节点构成了一个子树,那么仅仅记录最后一个值小于 p 的节点可能不足以确定正确的后继。在这种情况下,正确的后继应该是等于 p 值的节点的子树中的最左节点,或者是这些节点的父节点的后继,取决于具体的树结构。
这种处理不完全正确。根节点没有右子树不一定意味着它就没有中序后继。如果根节点是整棵树的最大值,确实没有中序后继;但如果根节点参与了更大的树结构,例如作为另一个树节点的左子树,那么根节点的后继应该是其父节点。因此,题解的这部分代码应该考虑根节点在整个树结构中的位置,而不应该仅仅因为它是根节点就断定没有后继。