文章目录
530. 二叉搜索树的最小绝对差
给你一个二叉搜索树的根节点 root
,返回 树中任意两不同节点值之间的最小差值 。
差值是一个正数,其数值等于两值之差的绝对值。
示例 1:
输入:root = [4,2,6,1,3]
输出:1
示例 2:
输入:root = [1,0,48,null,null,12,49]
输出:1
提示:
- 树中节点的数目范围是 [2, 10^4]
- 0 <= Node.val <= 10^5
注意
:本题与783. 二叉搜索树节点最小距离 相同
思路
题目中要求在二叉搜索树上任意两节点的差的绝对值的最小值。
注意是二叉搜索树,二叉搜索树可是有序的。
遇到在二叉搜索树上求什么最值啊,差值之类的,就把它想成在一个有序数组上求最值,求差值,这样就简单多了。
递归
那么二叉搜索树采用中序遍历,其实就是一个有序数组。
在一个有序数组上求两个数最小差值,这是不是就是一道送分题了。
最直观的想法,就是把二叉搜索树转换成有序数组,然后遍历一遍数组,就统计出来最小差值了。
Go
代码如下:
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func getMinimumDifference(root *TreeNode) int {
// 二叉搜索树中序遍历后就是有序的,得到数组后,相邻两个数的最小差值就是整棵树两节点之间的最小差值
arr := make([]int,0)
dfs(root,&arr)
res := math.MaxInt32
for i := 1;i < len(arr);i++ {
// 因为有序,后一个数减去前一个数一定是正数,不必取绝对值了
if arr[i] - arr[i-1] < res {
res = arr[i] - arr[i - 1]
}
}
return res
}
func dfs(root *TreeNode,arr *[]int) {
if root == nil {
return
}
dfs(root.Left,arr)
*arr = append(*arr,root.Val)
dfs(root.Right,arr)
}
以上代码是把二叉搜索树转化为有序数组了,其实在二叉搜素树中序遍历的过程中,我们就可以直接计算了。
需要用一个pre
节点记录一下cur
节点的前一个节点。
如图:
一些同学不知道在递归中如何记录前一个节点的指针,其实实现起来是很简单的,大家只要看过一次,写过一次,就掌握了。
代码如下:
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
// 中序遍历的同时计算最小值
func minDiffInBST(root *TreeNode) int {
// 保留前一个节点的指针
var prev *TreeNode
// 定义一个比较大的值
min := math.MaxInt64
var travel func(node *TreeNode)
travel = func(node *TreeNode) {
if node == nil {
return
}
travel(node.Left)
if prev != nil && node.Val - prev.Val < min {
min = node.Val - prev.Val
}
prev = node // 记录前一个节点
travel(node.Right)
}
travel(root)
return min
}
是不是看上去也并不复杂!
迭代
下面我给出其中的一种中序遍历的迭代法,代码如下:
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func minDiffInBST(root *TreeNode) int {
// 保留前一个节点的指针
var prev *TreeNode
curTreeNode := root
res := math.MaxInt64
stack := make([]*TreeNode,0)
for curTreeNode != nil || len(stack) != 0 {
if curTreeNode != nil {
stack = append(stack,curTreeNode)
curTreeNode = curTreeNode.Left // 左
} else {
curTreeNode = stack[len(stack) - 1] // 中
stack = stack[0:len(stack) - 1]
if prev != nil && curTreeNode.Val - prev.Val < res {
res = curTreeNode.Val - prev.Val
}
prev = curTreeNode // 更新前一个节点指向
curTreeNode = curTreeNode.Right // 右
}
}
return res
}
总结
遇到在二叉搜索树上求什么最值,求差值之类的,都要思考一下二叉搜索树可是有序的,要利用好这一特点。
同时要学会在递归遍历的过程中如何记录前后两个指针,这也是一个小技巧,学会了还是很受用的。
后面我将继续介绍一系列利用二叉搜索树特性的题目。