Day21~530.二叉搜索树的最小绝对差、501.二叉搜索树中的众数、236. 二叉树的最近公共祖先

77 阅读3分钟

摘要

本文主要介绍了LeetCode二叉树的几个题目,包括530.二叉搜索树的最小绝对差、501.二叉搜索树中的众数、236. 二叉树的最近公共祖先。

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

1.1 思路

  • 同98.验证二叉搜索树,二叉搜索树的中序遍历是一个递增的数组;定义prev为前一个节点,minVal为前一个节点和当前节点的最小差值

1.2 代码

    TreeNode prev;
    int minVal = Integer.MAX_VALUE;
​
    public int getMinimumDifference(TreeNode root) {
        doGetMinimumDifference(root);
        return minVal;
    }
​
    public void doGetMinimumDifference(TreeNode root) {
        if(root == null) {
            return;
        }
​
        getMinimumDifference(root.left);
​
        if(prev != null) {
            minVal = Math.min(minVal, root.val-prev.val);
        }
        prev = root;
        
        getMinimumDifference(root.right);
    }

2、501.二叉搜索树中的众数

2.1 思路

  • 二叉搜索树的中序遍历是一个递增的数组

  • 定义prev为前一个元素,count表示当前元素的出现频率,maxCount表示最高频率,list用于存储元素

  • 递归过程:

    1. 计数,prev为null或者prev与当前节点的值不等设置count=1,否则count++
    2. 更新maxCount和list(判断众数),如果count大于maxCount,list有且仅有当前元素,所以重置list并保存当前元素,更新maxCount=count,如果count等于maxCount,list添加相同次数的元素,如果count小于maxCount,不做任何操作
  • 最后将list转换为int数组

2.2 代码

    List<Integer> list = new ArrayList<>();
    TreeNode prev = null;
    int maxCount = 0;
    int count = 0;
​
    public int[] findMode(TreeNode root) {
        doFindMode(root);
​
        int[] arr = new int[list.size()];
        for(int i=0; i<list.size(); i++) {
            arr[i] = list.get(i);
        }
        return arr;
    }
​
    public void doFindMode(TreeNode root) {
        if(root == null) {
            return;
        }
​
        doFindMode(root.left);
        
        // 计数
        if(prev == null || root.val != prev.val) {
            count = 1;
        } else {
            count++;
        }
        // 更新maxCount和list
        if(count > maxCount) {
            list.clear();
            list.add(root.val);
            maxCount = count;
        } else if(count == maxCount) {
            list.add( root.val);
        }
        prev = root;
        
        doFindMode(root.right);
    }

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

3.1 思路

202102041512582.png

  • 后序遍历(左右中),其中null表示没有找到,不为null表示该节点是p或者q或者是最近公共祖先

    • 若未找到节点 p 或 q,返回 null;
    • 若找到一个节点,返回left or right
    • 若找到两个节点,返回 root

1、为什么需要 root == q,或者 root == p 是终止条件,而不是写在递归逻辑中?

写在终止条件中可以很好区别于当前节点不为空但不等于p,q的情况,如果写在递归逻辑中则不容易判断; 当在终止条件加入该判断后,如果是当前节点等于p或q 直接返回,如果当前节点不为空但不等于p,q 则会继续调用递归,并且因为左右子树都为 null 则也会返回null,符合逻辑。

3.2 代码

    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) {
            return null;
        } else if(left != null && right == null) {
            return left;
        } else if(left == null && right != null) {
            return right;
        } else {
            return root;
        }
    }

参考资料

代码随想录-二叉搜索树的最小绝对差

代码随想录-二叉搜索树中的众数

代码随想录-二叉树的最近公共祖先