代码随想录算法训练营第二十一天|530.二叉搜索树的最小绝对差、501.二叉搜索树中的众数、236. 二叉树的最近公共祖先

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

题目链接:530.二叉搜索树的最小绝对差
文档讲解:代码随想录
状态:还可以

思路:使用中序遍历来遍历二叉搜索树。在中序遍历过程中,比较当前节点和前驱节点的值,更新最小差值。返回二叉搜索树中任意两个节点值的最小差值。

递归:

int min = Integer.MAX_VALUE;
// 前驱节点
TreeNode pre;

public int getMinimumDifference(TreeNode root) {
    // 如果当前节点为空,返回0
    if (root == null) {
        return 0;
    }
    // 递归遍历左子树
    getMinimumDifference(root.left);
    
    // 如果前驱节点不为空,计算当前节点和前驱节点的值差
    if (pre != null) {
        int dif = root.val - pre.val;
        // 更新最小差值
        min = Math.min(min, dif);
    }
    // 更新前驱节点为当前节点
    pre = root;
    
    // 递归遍历右子树
    getMinimumDifference(root.right);
    // 返回最小差值
    return min;
}

迭代:

public int bfs(TreeNode root) {
    // 使用双端队列模拟栈
    Deque<TreeNode> stack = new LinkedList<>();
    // 初始化前驱节点值为最大整数
    int pre = Integer.MAX_VALUE;
    // 初始化最小差值为一个很大的数值
    int min = Integer.MAX_VALUE;
    
    // 如果根节点为空,返回0
    if (root == null) {
        return 0;
    }
    
    // 将根节点添加到栈中
    stack.addLast(root);
    
    // 当栈不为空时,继续遍历
    while (!stack.isEmpty()) {
        // 弹出栈顶元素
        TreeNode node = stack.pollLast();
        
        if (node != null) {
            // 先处理右子树
            if (node.right != null) {
                stack.addLast(node.right);
            }
            // 中间节点处理两次,设置一个null标记
            stack.addLast(node);
            stack.addLast(null);
            // 再处理左子树
            if (node.left != null) {
                stack.addLast(node.left);
            }
        } else {
            // 第二次遇到中间节点,进行实际处理
            node = stack.pollLast();
            // 计算当前节点与前驱节点的差值,并更新最小差值
            min = Math.min(Math.abs(node.val - pre), min);
            // 更新前驱节点的值
            pre = node.val;
        }
    }
    // 返回最小差值
    return min;
}

501.二叉搜索树中的众数

在这里插入图片描述

题目链接:501.二叉搜索树中的众数
文档讲解:代码随想录
状态:还行,能做出来,虽然不是最优解

思路:通过中序遍历二叉搜索树,在遍历过程中统计每个节点值的出现次数,并找到出现次数最多的节点值。

题解:

public class FindMode {
    // 存储众数的列表
    List<Integer> list = new LinkedList<>();

    public int[] findMode(TreeNode root) {
        // 调用 getCount 方法遍历二叉树并找到众数
        getCount(root);
        
        // 将 list 转换为数组
        int[] res = new int[list.size()];
        for (int i = 0; i < res.length; i++) {
            res[i] = list.get(i);
        }
        return res;
    }

    // 前一个节点的值,初始值为最小整数
    int preVal = Integer.MIN_VALUE;
    // 当前值出现的次数
    int count = 0;
    // 最大出现次数
    int max = Integer.MIN_VALUE;

    public void getCount(TreeNode root) {
        if (root == null) {
            return;
        }
        // 递归遍历左子树
        getCount(root.left);
        
        // 如果当前节点值等于前一个节点值,增加计数
        if (preVal == root.val) {
            count += 1;
        } else {
            // 如果当前节点值不等于前一个节点值,重置计数
            count = 1;
        }
        
        // 如果当前计数大于最大计数,清空列表并更新最大计数
        if (count > max) {
            list.clear();
            max = count;
            list.add(root.val);
        } else if (count == max) {
            // 如果当前计数等于最大计数,将当前值加入列表
            list.add(root.val);
        }
        
        // 更新前一个节点值为当前节点值
        preVal = root.val;
        
        // 递归遍历右子树
        getCount(root.right);
    }

}

236. 二叉树的最近公共祖先

在这里插入图片描述

题目链接:236. 二叉树的最近公共祖先
文档讲解:代码随想录
状态:想到使用后序遍历,但是判断逻辑没想出来(只想到true或false判断是否包含p,q,没想到使用返回节点和null来代替)

思路:使用后序遍历可以先获取左右子树的信息,然后利用左右子树信息和p,q比较从而实现判断逻辑。

题解:

    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        // 如果根节点为空或根节点是p或q之一,则直接返回根节点
        if (root == null || root == p || root == q) {
            return root;
        }

        // 在左子树中查找最近公共祖先
        TreeNode left = lowestCommonAncestor(root.left, p, q);
        // 在右子树中查找最近公共祖先
        TreeNode right = lowestCommonAncestor(root.right, p, q);

        // 如果p和q分别在当前根节点的左右子树中,则当前根节点是最近公共祖先
        if (left != null && right != null) {
            return root;
        }

        // 如果左子树中找到了p或q(即left不为空),返回left
        if (left != null) {
            return left;
        }

        // 如果右子树中找到了p或q(即right不为空),返回right
        if (right != null) {
            return right;
        }

        // 如果左右子树中都没有找到p或q,返回null
        return null;
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值