![2088173e6eec2ce0bdf0d5e68e7ebd36.png](https://i-blog.csdnimg.cn/blog_migrate/d4d51d87ad77108cc3031e695952ccc4.jpeg)
题目介绍
描述:
给定一个二叉搜索树的根节点 root,返回树中任意两节点的差的最小值。
示例:
输入: root = [4,2,6,1,3,null,null]
输出: 1
解释:
注意,root是树节点对象(TreeNode object),而不是数组。
给定的树 [4,2,6,1,3,null,null] 可表示为下图:
4
/
2 6
/
1 3
最小的差值是 1, 它是节点1和节点2的差值, 也是节点3和节点2的差值。
注意:
二叉树的大小范围在 2 到 100。
二叉树总是有效的,每个节点的值都是整数,且不重复。
解题思路:
递归算法的关键是要明确函数的「定义」是什么,然后相信这个定义,利用这个定义推导最终结果。
写树相关的算法,简单说就是,先搞清楚当前 root 节点该做什么,然后根据函数定义递归调用子节点,递归调用会让孩子节点做相同的事情。
二叉树题目的一个难点在于如何通过题目的要求思考出每一个节点需要做什么
二叉树解题策略
一 递归 二 队列 + 迭代 (层次遍历) 三 栈 + 迭代 (非递归遍历) 四 其它
三种基本的遍历方式,都可以用递归来实现。写递归算法的时候,需要注意递归退出条件以及递归操作的表达。
最直观的想法,得到所有节点的值,依次减去下一个,看下哪个最小
自己的解法实现
def minDiffInBST(self, root):
if not root: return 0
stack, res = [root], []
while stack:
node = stack.pop(0)
res.append(node.val)
if node.left:
stack.append(node.left)
if node.right:
stack.append(node.right)
res.sort()
return min([abs(res[i] - res[i + 1]) for i in range(len(res) - 1)])
网上比较优秀的解法
解法一
将树中所有节点的值写入数组,之后将数组排序。依次计算相邻数之间的差值,找出其中最小的值。
def minDiffInBST2(self, root):
vals = []
def dfs(node):
if node:
vals.append(node.val)
dfs(node.left)
dfs(node.right)
dfs(root)
vals.sort()
temp = [vals[i + 1] - vals[i] for i in range(len(vals) - 1)]
return min(temp)
解法二
方法二:中序遍历【通过】 思路和算法 在二叉搜索树中,中序遍历会将树中节点按数值大小顺序输出。只需要遍历计算相邻数的差值,取其中最小的就可以了。
def minDiffInBST3(self, root):
def dfs(node):
if node:
dfs(node.left)
self.ans = min(self.ans, node.val - self.prev)
self.prev = node.val
dfs(node.right)
self.prev = float('-inf')
self.ans = float('inf')
dfs(root)
return self.ans
解法三
二叉搜索树的中序遍历是升序数组。
比如对于样例输入 root = [4,2,6,1,3,null,null],中序遍历的结果就是 [1, 2, 3, 4, 6]。
题目要求两个结点的最小距离,就是要求中序遍历数组里相邻两个元素差的最小值。
def minDiffInBST4(self, root):
def inorder(node):
if not node: return []
return inorder(node.left) + [node.val] + inorder(node.right)
res = float('inf')
_list = inorder(root)
for i in range(1, len(_list)):
res = min(res, _list[i] - _list[i - 1])
return res
相关知识总结和思考
相关知识:
BFS:广度/宽度优先。其实就是从上到下,先把每一层遍历完之后再遍历一下一层。
可以使用Queue的数据结构。我们将root节点初始化进队列,通过消耗尾部,插入头部的方式来完成BFS。
二叉搜索树(BST)的特性:
- 若它的左子树不为空,则所有左子树上的值均小于其根节点的值
- 若它的右子树不为空,则所有右子树上的值均大于其根节点的值
- 它的左右子树也分别为二叉搜索树
递归与迭代的区别
递归:重复调用函数自身实现循环称为递归; 迭代:利用变量的原值推出新值称为迭代,或者说迭代是函数内某段代码实现循环;