题目
标题和出处
标题:二叉搜索树的最小绝对差
难度
3 级
题目描述
要求
给定一个二叉搜索树的根结点 root \texttt{root} root,返回树中任意两个不同结点值之间的差值绝对值的最小值。
示例
示例 1:
输入:
root
=
[4,2,6,1,3]
\texttt{root = [4,2,6,1,3]}
root = [4,2,6,1,3]
输出:
1
\texttt{1}
1
示例 2:
输入:
root
=
[1,0,48,null,null,12,49]
\texttt{root = [1,0,48,null,null,12,49]}
root = [1,0,48,null,null,12,49]
输出:
1
\texttt{1}
1
数据范围
- 树中结点数目在范围 [2, 10 4 ] \texttt{[2, 10}^\texttt{4}\texttt{]} [2, 104] 内
- 0 ≤ Node.val ≤ 10 5 \texttt{0} \le \texttt{Node.val} \le \texttt{10}^\texttt{5} 0≤Node.val≤105
解法一
思路和算法
由于二叉搜索树的中序遍历序列是单调递增的,因此只要得到二叉搜索树的中序遍历序列,然后计算序列中的每一对相邻结点值之差的绝对值,其中的最小值即为任意两个不同结点值之间的差值绝对值的最小值。
由于只是计算二叉搜索树的中序遍历序列中的每一对相邻结点值之差的绝对值,因此不需要存储完整的中序遍历序列,而是只需要存储上一个遍历到的结点值。每次访问结点时,当前结点值一定大于上一个结点值,因此计算当前结点值与上一个结点值之差,即为相邻结点值之差的绝对值。遍历结束之后,即可得到任意两个不同结点值之差的绝对值的最小值。
代码
class Solution {
public int getMinimumDifference(TreeNode root) {
int minDiff = Integer.MAX_VALUE;
Deque<TreeNode> stack = new ArrayDeque<TreeNode>();
int prev = Integer.MIN_VALUE / 10;
TreeNode node = root;
while (!stack.isEmpty() || node != null) {
while (node != null) {
stack.push(node);
node = node.left;
}
node = stack.pop();
minDiff = Math.min(minDiff, node.val - prev);
prev = node.val;
node = node.right;
}
return minDiff;
}
}
复杂度分析
-
时间复杂度: O ( n ) O(n) O(n),其中 n n n 是二叉搜索树的结点数。每个结点都被访问一次。
-
空间复杂度: O ( n ) O(n) O(n),其中 n n n 是二叉搜索树的结点数。空间复杂度主要是栈空间,取决于二叉搜索树的高度,最坏情况下二叉搜索树的高度是 O ( n ) O(n) O(n)。
解法二
思路和算法
解法一虽然不需要存储中序遍历序列,但是仍需要使用栈空间。使用莫里斯遍历可以将空间复杂度降低到 O ( 1 ) O(1) O(1)。
遍历过程中维护上一个结点值。每次访问结点时,计算当前结点值与上一个结点值之差。遍历结束之后,即可得到任意两个不同结点值之差的绝对值的最小值。
代码
class Solution {
public int getMinimumDifference(TreeNode root) {
int minDiff = Integer.MAX_VALUE;
int prev = Integer.MIN_VALUE / 10;
TreeNode node = root;
while (node != null) {
if (node.left == null) {
minDiff = Math.min(minDiff, node.val - prev);
prev = node.val;
node = node.right;
} else {
TreeNode predecessor = node.left;
while (predecessor.right != null && predecessor.right != node) {
predecessor = predecessor.right;
}
if (predecessor.right == null) {
predecessor.right = node;
node = node.left;
} else {
predecessor.right = null;
minDiff = Math.min(minDiff, node.val - prev);
prev = node.val;
node = node.right;
}
}
}
return minDiff;
}
}
复杂度分析
-
时间复杂度: O ( n ) O(n) O(n),其中 n n n 是二叉搜索树的结点数。使用莫里斯遍历,每个结点最多被访问两次。
-
空间复杂度: O ( 1 ) O(1) O(1)。