【LeetCode】530. 二叉搜索树的最小绝对差

137 阅读1分钟

「这是我参与2022首次更文挑战的第26天,活动详情查看:2022首次更文挑战」。

题目

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

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

示例 1

img

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

示例 2

img

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

提示

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

题解

思路

看到二叉搜索树,应该能想到中序遍历。

遍历一个二叉树,会访问每一个节点,拿节点做一些事情。

而中序遍历,它对于每一个节点,都先访问处理它的左子树中的节点,再访问处理它本身,再访问处理它的右子树中的节点。

由于二叉搜索树的性质,中序遍历访问处理的节点值的大小是递增的。

题目要求任意两个节点的最小的差值,它肯定发生在递增排列后的相邻的节点值之间。

我们用一个变量,保存上一个访问处理的节点值,求出当前访问的节点值与它之差,挑战最小的纪录,更小就更新。

从定义理解中序遍历

中序遍历基于 DFS,要对每一个节点做一些事情,做同样的事情。

前、中、后序遍历的区别在于,拿节点做一些事情的先后顺序不同。

中序遍历是,对每一个节点,先对它的左子树中的节点执行这些事情,再对当前节点执行这些逻辑,然后对节点的右子树中的节点执行相同的逻辑。

在 DFS 时,有三个阶段会碰到一个节点:

  • 递归它的左子树之前
  • 递归完它的左子树之后,递归它的右子树之前
  • 递归完它的左、右子树之后

我们选择在递归它的左子树之后,递归它的右子树之前这个阶段,去执行我们处理节点的逻辑,就是中序遍历。

代码

const getMinimumDifference = (root) => {
  let diff = Number.MAX_SAFE_INTEGER;
  let preVal;

  const inOrder = (root) => {
    if (root == null) {
      return;
    }
    inOrder(root.left);
    if (preVal !== undefined && root.val - preVal < diff) {
      diff = root.val - preVal;
    }
    preVal = root.val;
    inOrder(root.right);
  };

  inOrder(root);
  return diff;
}

结语

业精于勤,荒于嬉;行成于思,毁于随。