530.二叉搜索树的最小绝对差
530. 二叉搜索树的最小绝对差 - 力扣(LeetCode)
不愧是搜索树,这次搜索有方向了!| LeetCode:700.二叉搜索树中的搜索_哔哩哔哩_bilibili
给你一个二叉搜索树的根节点
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
注意:本题与 783 . - 力扣(LeetCode) 相同
刚开始没什么思路,因为忽视了二叉搜索树的特点:
二叉搜索树是一个有序树,有如下特点:
1、若它的左子树不为空,则左子树上所有节点的值均小于根节点的值;
2、若它的右子树不为空,则右子树上所有节点的值均大于根节点的值;
3、它的左右子树也分别为二叉搜索树
二叉搜索树在中序遍历的时候其实就是一个有序数组。
遍历有序数组求最小差值常用双指针法。
那在二叉树中,双指针应该如何摆放呢?如图:红色线条为cur指针的路线,pre指针紧随其后。
递归三部曲:
1、确定参数和返回值:传入的参数是根节点root,返回值是int类型的result值
public int getMinimumDifference(TreeNode root){
if(root == null){
return 0;
treeversal (root);//采用中序遍历遍历二叉树
return result;
}
}
2、确定终止条件:cur为空时,终止遍历:
// 中序遍历二叉搜索树,记录最小差值
public void traversal(TreeNode root) {
if(root == null) // 如果当前节点为空,直接返回
return;
3、确定单层递归的逻辑:如果当前节点不为空,则求当前节点和前一个节点的差,将差值和min比较,求最小值
if(pre != null) { // 如果pre不为空,说明当前节点不是树中的第一个节点
result = Math.min(result, root.val - pre.val); // 更新最小差值
}
pre = root; // 更新pre为当前节点
综合代码:
class Solution {
TreeNode pre; // 用于记录上一个遍历的结点
int result = Integer.MAX_VALUE; // 用于记录结果,默认为最大整数值
// 公共方法,用于获取二叉搜索树中任意两个节点值的最小差值
public int getMinimumDifference(TreeNode root) {
if(root == null) // 如果根节点为空,直接返回0
return 0;
traversal(root); // 调用traversal方法进行中序遍历
return result; // 返回最小差值
}
// 中序遍历二叉搜索树,记录最小差值
public void traversal(TreeNode root) {
if(root == null) // 如果当前节点为空,直接返回
return;
// 左子树遍历
traversal(root.left);
// 中间节点处理
if(pre != null) { // 如果pre不为空,说明当前节点不是树中的第一个节点
result = Math.min(result, root.val - pre.val); // 更新最小差值
}
pre = root; // 更新pre为当前节点
// 右子树遍历
traversal(root.right);
}
}
501.二叉搜索树中的众数
不仅双指针,还有代码技巧可以惊艳到你! | LeetCode:501.二叉搜索树中的众数_哔哩哔哩_bilibili
给你一个含重复值的二叉搜索树(BST)的根节点
root
,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。如果树中有不止一个众数,可以按 任意顺序 返回。
假定 BST 满足如下定义:
- 结点左子树中所含节点的值 小于等于 当前节点的值
- 结点右子树中所含节点的值 大于等于 当前节点的值
- 左子树和右子树都是二叉搜索树
示例 1:
输入:root = [1,null,2,2] 输出:[2]示例 2:
输入:root = [0] 输出:[0]
第一反应和上一题一样用双指针法。这棵树是二叉搜索树,本身就是有序的,如果有相同的值,相同的值也应该相邻。那有值反复出现的时候,怎么计算这个值出现了几次呢?
看了卡哥的题解,用count来统计相同的值出现的次数,同时还用maxCount来统计出现的次数的最大值。
class Solution {
ArrayList<Integer> resList; // 用于存储结果的列表
int maxCount; // 最大的出现次数
int count; // 当前节点值出现的次数
TreeNode pre; // 记录前一个遍历的节点
// 寻找二叉搜索树中的众数
public int[] findMode(TreeNode root) {
// 初始化变量
resList = new ArrayList<>();
maxCount = 0;
count = 0;
pre = null;
// 执行查找众数的方法
findMode1(root);
// 将结果转换为数组
int[] res = new int[resList.size()];
for (int i = 0; i < resList.size(); i++) {
res[i] = resList.get(i);
}
return res; // 返回结果数组
}
// 递归方法,用于查找众数
public void findMode1(TreeNode root) {
if (root == null) { // 如果当前节点为空,直接返回
return;
}
findMode1(root.left); // 遍历左子树
int rootValue = root.val; // 当前节点的值
// 计数
if (pre == null || rootValue != pre.val) { // 如果pre为空或者当前节点值与pre不同
count = 1; // 重置count为1
} else {
count++; // 否则count加1
}
// 更新结果以及maxCount
if (count > maxCount) { // 如果当前节点出现的次数大于最大出现次数
resList.clear(); // 清空结果列表
resList.add(rootValue); // 添加当前节点值到结果列表
maxCount = count; // 更新最大出现次数
} else if (count == maxCount) { // 如果当前节点出现的次数等于最大出现次数
resList.add(rootValue); // 直接添加当前节点值到结果列表
}
pre = root; // 更新pre为当前节点
findMode1(root.right); // 遍历右子树
}
}