二叉搜索树的最小绝对差

标签: 深度优先搜索 广度优先搜索 二叉搜索树 二叉树

难度: Easy

给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值

差值是一个正数,其数值等于两值之差的绝对值。

示例 1:

输入:root = [4,2,6,1,3]
输出:1

示例 2:

输入:root = [1,0,48,null,null,12,49]
输出:1

提示:

  • 树中节点的数目范围是 [2, 104]
  • 0 <= Node.val <= 105

注意:本题与 783 https://leetcode-cn.com/problems/minimum-distance-between-bst-nodes/ 相同

Submission

运行时间: 68 ms

内存: 17.2 MB

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def getMinimumDifference(self, root: Optional[TreeNode]) -> int:
        stack = []
        lastVal = None
        minAbs = 10**5+1
        while root is not None or len(stack) > 0:
            if root is not None:
                stack.append(root)
                root = root.left
            else:
                root = stack.pop()
                if lastVal is not None:
                    minAbs = min(minAbs, root.val - lastVal)
                lastVal = root.val
                root = root.right
        return minAbs

Explain

这个题解采用了中序遍历二叉搜索树的思路。由于二叉搜索树的中序遍历结果是一个升序序列,所以我们可以在中序遍历的过程中,记录上一个遍历到的节点值 lastVal,并用当前节点值与 lastVal 的差值来更新最小绝对差 minAbs。这样在遍历完整棵树后,minAbs 就是任意两节点差值的最小值。

时间复杂度: O(n)

空间复杂度: O(n)

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def getMinimumDifference(self, root: Optional[TreeNode]) -> int:
        stack = []
        lastVal = None
        minAbs = 10**5+1
        
        while root is not None or len(stack) > 0:
            if root is not None:
                stack.append(root)
                root = root.left  # 向左子树遍历
            else:
                root = stack.pop()  # 弹出栈顶节点
                if lastVal is not None:
                    minAbs = min(minAbs, root.val - lastVal)  # 更新最小绝对差
                lastVal = root.val  # 记录当前节点值
                root = root.right  # 向右子树遍历
        
        return minAbs

Explore

在二叉搜索树(BST)中,中序遍历会按照升序的顺序访问所有节点。因此,相邻两个节点的值之差是所有可能的相邻节点对中差值的最小值。通过比较连续节点的值,我们能够找到整个树中任意两个节点之间的最小绝对差。

基于栈的非递归中序遍历方法与递归方法相比,主要优点是可以避免递归造成的栈溢出,特别是在深度很大的树中。此外,非递归方法的控制流更为明确,有时更易于理解和调试。然而,其缺点包括可能更复杂的编码实现,以及在某些情况下,手动管理栈可能会比自动的函数调用栈更加低效。

这个初始值选择是基于题目对节点值的一般范围假设(例如,节点值可能的最大范围)。这种设定是为了确保在实际的节点值差异计算中,任何实际的差值都会小于这个初始值,从而确保正确更新最小差值。然而,更合理的初始值可以是无穷大(如Python中的float('inf')),这样可以避免对节点值范围的假设,并且使得算法更加通用。

严格来说,标准的二叉搜索树不应该包含重复元素,因为这会破坏树的性质。如果二叉搜索树被修改允许重复元素(例如,左子树中的元素严格小于根,右子树中的元素大于等于根),当前算法仍然有效,因为它只关心节点值的差异。然而,如果存在重复元素,最小绝对差可能是0,算法需要能够正确处理这种情况。