代码随想录Day21 - 二叉树

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

给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值 。
差值是一个正数,其数值等于两值之差的绝对值。

题目中要求在二叉搜索树上任意两节点的差的绝对值的最小值,而二叉搜索树是有序的。二叉搜索树采用中序遍历,其实就是一个有序数组(题目等同于在一个有序数组中找两个数最小差值)。

递归法

注意:学会在递归遍历的过程中如何记录前后两个指针

完整代码如下:

class Solution {
    TreeNode pre; // 记录上一个遍历的结点
    int result = Integer.MAX_VALUE; //存放结果
    
    public int getMinimumDifference(TreeNode root) {
        getMin(root);
        return result;
    }

	//将结果存放在result中,所以不需要有返回值
    public void getMin(TreeNode cur){
        if(cur == null) return;
        getMin(cur.left); //左
        //中
        if(pre != null){
            result = Math.min(result, Math.abs(cur.val - pre.val)); 
        }
        pre = cur; 
        getMin(cur.right); //右
    }
}

迭代法(中序遍历)

使用中序遍历的

class Solution {
    TreeNode pre; // 记录上一个遍历的结点
    public int getMinimumDifference(TreeNode root) {
        if(root == null) return 0;
        Stack<TreeNode> stack = new Stack<>();
        int result = Integer.MAX_VALUE;
        
        TreeNode cur = root;
        while(cur != null || !stack.isEmpty()){
            if(cur != null){
                stack.push(cur);
                cur = cur.left; //左
            }else{
                cur = stack.pop();
                //处理逻辑,中
                if(pre != null){
                    result = Math.min(result, cur.val - pre.val);
                }
                pre = cur;
                cur = cur.right; //右
            }
        }
        return result;
    }
}

501.二叉搜索树中的众数

给你一个含重复值的二叉搜索树(BST)的根节点 root ,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。
如果树中有不止一个众数,可以按 任意顺序 返回。

递归法(中序遍历)

在上一题503:搜索树的最小绝对差 中我们就使用了pre指针和cur指针的技巧,这次又用上了。

弄一个指针指向前一个节点,这样每次cur(当前节点)才能和pre(前一个节点)作比较。

class Solution {
    TreeNode pre; //记录前一个遍历的节点
    int count = 0; //统计每个元素出现的次数
    int maxcount = 0; //统计出现的最大次数
    List<Integer> result = new ArrayList<>(); //存放众数结果

    public int[] findMode(TreeNode root) {
        find(root);
        int[] res = new int[result.size()];
        for (int i = 0; i < result.size(); i++) {
            res[i] = result.get(i);
        }
        return res;
    }

    //结果存放在result中,不需要返回值
    public void find(TreeNode root){
        if(root == null) return;

        find(root.left); //左

		//中
        if(pre == null){  第一个节点
            count = 1;
        }else if(pre.val == root.val){ // 与前一个节点数值相同
            count++;
        }else if(pre.val != root.val){ // 与前一个节点数值不同
            count = 1;
        }

        //众数可能不止一个
        if(count == maxcount) result.add(root.val);
        if(count > maxcount){
            result.clear();
            result.add(root.val);
            maxcount = count;
        }
        pre = root; // 更新上一个节点

        find(root.right); //右
    }
}

迭代法(中序遍历)

迭代法,其实就是迭代法中序遍历的模板加上递归法中中间节点的处理逻辑

class Solution {
    public int[] findMode(TreeNode root) {
        TreeNode pre = null;
        Stack<TreeNode> stack = new Stack<>();
        List<Integer> result = new ArrayList<>();
        int maxcount = 0;
        int count = 0;
        TreeNode cur = root;
        while (cur != null || !stack.isEmpty()) {
            if (cur != null) {
                stack.push(cur);
                cur =cur.left;
            }else {
                cur = stack.pop();
                // 计数
                if(pre == null){  第一个节点
                    count = 1;
                }else if(pre.val == cur.val){ // 与前一个节点数值相同
                    count++;
                }else if(pre.val != cur.val){ // 与前一个节点数值不同
                    count = 1;
                }

                //众数可能不止一个
                if(count == maxcount) result.add(cur.val);
                if(count > maxcount){
                    result.clear();
                    result.add(cur.val);
                    maxcount = count;
                }
                pre = cur; // 更新上一个节点
                cur = cur.right;
            }
        }
        return result.stream().mapToInt(Integer::intValue).toArray();
    }
}

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

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

需要递归函数返回值,来告诉我们是否找到节点q或者p

求最小公共祖先,需要从底向上遍历,那么二叉树需要通过后序遍历实现从底向上的遍历方式。

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

如果left 和 right都不为空,说明此时root就是最近公共节点;如果left为空,right不为空,就返回right,说明目标节点是通过right返回的,反之依然。

递归法(后序遍历)

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root == null) return null;
        if(root == p || root == q) return root;

        TreeNode left = lowestCommonAncestor(root.left, p, q); //左
        TreeNode right = lowestCommonAncestor(root.right, p, q); //右
         
         //中
        if(left == null && right == null) { // 若未找到节点 p 或 q
            return null;
        }else if(left == null && right != null) { // 若找到一个节点
            return right;
        }else if(left != null && right == null) { // 若找到一个节点
            return left;
        }else { // 若找到两个节点
            return root;
        }   
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值