代码随想录第21天 | 530.二叉搜索树的最小绝对差 501.二叉搜索树中的众数

530.二叉搜索树的最小绝对差 

530. 二叉搜索树的最小绝对差 - 力扣(LeetCode)

代码随想录 (programmercarl.com)

不愧是搜索树,这次搜索有方向了!| 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.二叉搜索树中的众数

501. 二叉搜索树中的众数 - 力扣(LeetCode)

代码随想录 (programmercarl.com)

不仅双指针,还有代码技巧可以惊艳到你! | 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); // 遍历右子树
    }
}

  • 27
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值