530. 二叉搜索树的最小绝对差 + 783. 二叉搜索树节点最小距离
原题
给你一个二叉搜索树的根节点 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
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public int getMinimumDifference(TreeNode root) {
}
}
解题思路
- 二叉搜索树,也叫二叉查找树、二叉排序树,满足以下性质:
- 若其左子树非空,则左子树上所有节点的值均小于根节点的值;
- 若其左子树非空,则右子树上所有节点的值均大于等于根节点的值;
- 其左右子树本身又各是一棵二叉搜索树。
- 二叉搜索树有一个重要的性质:
中序遍历非空的二叉搜索树所得到的数据元素序列是一个按照关键字排列的递增有序序列。 - 根据该性质,可以将二叉搜索树经过中序遍历转换成升序序列。而对于升序序列求任意两个元素之差的绝对值的最小值,答案一定为相邻两个元素之差的最小值。逐个计算相邻元素差值并存储最小结果即为答案。
代码示例
class Solution {
public int getMinimumDifference(TreeNode root) {
// 初始化最小差值为整型最大值
int minimumResult = Integer.MAX_VALUE;
// 存储中序遍历结果
List<Integer> traversalResult = new ArrayList<>();
inorderTraversal(root, traversalResult);
// 计算相邻节点值的差值并更新最小差值
for (int i = 0; i < traversalResult.size() - 1; i++) {
minimumResult = Math.min(minimumResult, traversalResult.get(i+1) - traversalResult.get(i));
}
return minimumResult;
}
// 中序遍历二叉树节点并将值存储在列表中
private List<Integer> inorderTraversal(TreeNode node, List<Integer> list) {
if (node != null) {
// 递归遍历左子树
inorderTraversal(node.left, list);
// 将当前节点值添加到列表
list.add(node.val);
// 递归遍历右子树
inorderTraversal(node.right, list);
}
return list;
}
}
优化思路
为了减少内存开销,可以在中序遍历的同时比较相邻节点值,而不是将遍历结果存储在列表中。
优化后代码
class Solution {
// 用于存储中序遍历过程中上一个节点的值
int previousValue = -1;
// 初始化最小差值为整型最大值
int minimumResult = Integer.MAX_VALUE;
public int getMinimumDifference(TreeNode root) {
inorderTraversal(root);
return minimumResult;
}
public void inorderTraversal(TreeNode node) {
if (node != null) {
// 递归遍历左子树
inorderTraversal(node.left);
if (previousValue == -1) {
// previousValue 初始化为中序遍历第一个叶子节点的值
previousValue = node.val;
} else {
// 计算当前节点值与上一个节点值的差值,并更新最小差值
minimumResult = Math.min(minimumResult, node.val - previousValue);
// 将上一个节点的值置为当前节点的值并进入下一节点
previousValue = node.val;
}
// 递归遍历右子树
inorderTraversal(node.right);
}
}
}