数据结构刷题(十七):530二叉搜索树最小绝对差、501二叉搜索树中的众数、236二叉树的最近公共祖先、235二叉搜索树的最近公共祖先

一、二叉搜索树的最小绝对差

题目链接

思路: 中序遍历保留为list + for循环找最小绝对差

二叉搜索树中序遍历后是有序的数组!!

注意:i = 1开始遍历

解法:

public int getMinimumDifference(TreeNode root) {
    List<Integer> res = new ArrayList<>();
    inorder(root, res);
    int num = Integer.MAX_VALUE;
    for (int i = 1; i < res.size(); i++) {
        if (num > res.get(i) - res.get(i - 1))
            num = res.get(i) - res.get(i - 1);
    }
    return num;
}

private void inorder(TreeNode root, List<Integer> res) {
    if (root == null)
        return;
    inorder(root.left, res);
    res.add(root.val);
    inorder(root.right, res);
}

二、二叉搜索树中的众数

题目链接

思路:中序遍历的迭代法(stack);

注意:

  • pre是cur的前驱结点,便于比较

  • 更新count时要注意count=maxcount的情况;

  • 当出现count>maxcount时需要清空原先列表中保存的元素

解法:

public int[] findMode(TreeNode root) {

    TreeNode pre = null;
    Stack<TreeNode> stack = new Stack<>();
    // 结果列表
    List<Integer> res = new ArrayList<>();
    TreeNode cur = root;
    int count = 0;
    int maxcount = 0;

    while (cur != null || !stack.isEmpty()){
        if (cur != null){
            stack.push(cur);
            cur = cur.left;
        }else{
            cur = stack.pop();
            // 判断当前节点是否出现过 或者  当前节点值与上一个节点值是否相等
            if (pre == null || cur.val != pre.val)
                count = 1;
            else
                count++;
            // 更新count
            if (count > maxcount){
                maxcount = count;
                res.clear();
                res.add(cur.val);
            }else if (count == maxcount){
                res.add(cur.val);
            }
            // 及时更新
            pre = cur;
            cur = cur.right;
        }
    }
    // 使用stream()做数据映射
    // mapToInt:一个流中的元素转换为 int 类型
    // 双冒号就是把方法当做参数传到stream内部,使stream的每个元素都传入到该方法里面执行一下
    // 最后转换为array类型
    return res.stream().mapToInt(Integer::intValue).toArray();
}

三、二叉树的最近公共祖先

题目链接

思路:使用后序遍历(即回溯),

注意:

  • 还有一个情况,就是节点本身p,它拥有一个子孙节点q。

  • 在回溯的过程中,必然要遍历整棵二叉树,即使已经找到结果了,依然要把其他节点遍历完,因为要使用递归函数的返回值(也就是代码中的left和right)做逻辑判断。

  • 理解如果返回值left为空,right不为空为什么要返回right,为什么可以用返回right传给上一层结果。

过程图:(见代码随想录https://programmercarl.com/0236.%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E6%9C%80%E8%BF%91%E5%85%AC%E5%85%B1%E7%A5%96%E5%85%88.html#java

解法:

public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode 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 null;
    }else if (left == null && right != null){
        return right;
    }else if (left != null && right == null){
        return left;
    }else        // 返回的节点都不为空,说明这两个节点就是p和q;
        return root;
}

四、二叉搜索树的最近公共祖先

题目链接

思路:还是后序遍历 ;或者同上题,直接可以用上次代码

注意:只要当cur节点在区间(p->val <= cur->val && cur->val <= q->val)

或者 (q->val <= cur->val && cur->val <= p->val)中,那么cur就是最近公共祖先了,直接返回。

解法:

public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
    if (root.val > p.val && root.val > q.val) return lowestCommonAncestor(root.left, p, q);
    if (root.val < p.val && root.val < q.val) return lowestCommonAncestor(root.right, p, q);
    return root;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值