Swift - LeetCode - 二叉搜索树的最小绝对差

111 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第28天,点击查看活动详情

题目

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

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

示例 1:

image.png

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

示例 2:

image.png

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

方法一:中序遍历

思路及解法

考虑对升序数组 a 求任意两个元素之差的绝对值的最小值,答案一定为相邻两个元素之差的最小值,即

ans=mini=0n2{a[i+1]a[i]}\textit{ans}=\min_{i=0}^{n-2}\left\{a[i+1]-a[i]\right\}

其中 n 为数组 a 的长度。其他任意间隔距离大于等于 2 的下标对 (i,j) 的元素之差一定大于下标对 (i,i+1) 的元素之差,故不需要再被考虑。

回到本题,本题要求二叉搜索树任意两节点差的绝对值的最小值,而我们知道二叉搜索树有个性质为二叉搜索树中序遍历得到的值序列是递增有序的,因此我们只要得到中序遍历后的值序列即能用上文提及的方法来解决。

朴素的方法是经过一次中序遍历将值保存在一个数组中再进行遍历求解,我们也可以在中序遍历的过程中用 pre\textit{pre} 变量保存前驱节点的值,这样即能边遍历边更新答案,不再需要显式创建数组来保存,需要注意的是 pre\textit{pre} 的初始值需要设置成任意负数标记开头,下文代码中设置为 -1

二叉树的中序遍历有多种方式,包括递归、栈、Morris 遍历等,这里选择栈的方式。

代码

class Solution {
    var pre: Int = -1
    var ans: Int = Int.max
    
    func getMinimumDifference(_ root: TreeNode?) -> Int {
        dfs(root)
        return ans
    }
    
    func dfs(_ root: TreeNode?) {
        if nil == root {
            return
        }
        
        dfs(root?.left)
        
        if -1 == pre {
            pre = root!.val
        } else {
            ans = min(ans, abs(root!.val - pre))
            pre = root!.val
        }
        
        dfs(root?.right)
    }
}

复杂度分析

  • 时间复杂度:O(n)O(n),其中 nn 为二叉搜索树节点的个数。每个节点在中序遍历中都会被访问一次且只会被访问一次,因此总时间复杂度为 O(n)O(n)

  • 空间复杂度:O(n)O(n)。递归函数的空间复杂度取决于递归的栈深度,而栈深度在二叉搜索树为一条链的情况下会达到 O(n)O(n) 级别。