day18 || lc520二叉搜索树最小绝对差 || lc501二叉搜索树的众数 || lc236二叉树的最近公共祖先

day18

lc530_二叉搜索树的最小绝对差

给你一棵所有节点为非负值的二叉搜索树,请你计算树中任意相邻两节点的差的绝对值的最小值。

需要领悟一下二叉树遍历上双指针操作

提到二叉搜索树 在中序遍历 就是有序的

最直观的想法 就是先中序遍历 转变成有序数组 然后再数组中再去求相邻两个元素的最小绝对差

本题利用两个指针 直接得出绝对差 不转数组

public class Lc530_getMinimumDifference {

    Node pre;
    int res = Integer.MAX_VALUE;

    public int getMinimumDifference(Node root) {
        if(root == null) return 0;

        diGui(root);
        return res;
    }

    private void diGui(Node root) {
        if(root == null) return;
        //左
        diGui(root.l);
        //跟
        if(pre != null) res = Math.min(res, root.v - pre.v);
        pre = root;
        // 又
        diGui(root.r);

    }
    
}

遇到在二叉搜索树上求什么最值,求差值之类的,都要思考一下二叉搜索树可是有序的,要利用好这一特点。


lc501_二叉搜索树的众数

给定一个有相同值的二叉搜索树(BST),找出 BST 中的所有众数(出现频率最高的元素)。

假定 BST 有如下定义:

  • 结点左子树中所含结点的值小于等于当前结点的值
  • 结点右子树中所含结点的值大于等于当前结点的值
  • 左子树和右子树都是二叉搜索树

既然是二叉搜索树 那么他中序遍历就是有序的 小到大的顺序, 那么便利有序数组元素出现的频率 从头开始便利 那么一定是相邻两个元素做比较 因为是有序的 然后把出现频率最高的元素输出就可以了


跟节点处理逻辑:

使用双指针 pre = null cur

一个指针指向前一个节点 这样每次当前节点才能和pre前一个节点进行比较

而且初始化的时候pre = NULL,这样当pre为NULL时候,我们就知道这是比较的第一个元素。count = 1

如果pre == cur的时候 就统计count++ 这个count是单个元素出现的频率

如果!= cur 那么count重新初始化为1 只有相等的时候才会加count的值


收集结果:

如果count == maxCount的时候 就把这个元素放入res里面

频率count 大于 maxCount的时候,不仅要更新maxCount = count ,而且要清空结果集res ,因为结果集之前的元素都失效了。 然后把新的cur对应的val放入结果里面


package day18;

import java.util.ArrayList;

/**
 * lc501_.二叉搜索树中的众数
 * 系列详细代码请访问:https://github.com/WEIERHANG/leetcode
 */
public class Lc501_findMode {

    ArrayList<Integer> res; //结果
    int count, maxCount;  //当前出现频率, 最大频率
    Node pre;  //前一个节点

    public int[] findMode(Node root) {
        res = new ArrayList<>();
        maxCount = 0;
        count = 0;
        pre = null;
        findModeDiGui(root);
        // 转成结果数组并且返回
        int[] resArr = new int[res.size()];
        for(int i = 0; i < res.size(); i++) resArr[i] = res.get(i);
        return resArr;
    }

    private void findModeDiGui(Node root) {
        if (root == null) return;
        // 左
        findModeDiGui(root.l);
        // 根
        int rootVal = root.v;
        if(pre == null || rootVal != pre.v) count = 1;
        else count++;
        if(count > maxCount){
            res.clear();
            res.add(rootVal);
            maxCount = count;
        }else if(count == maxCount) res.add(rootVal);
        pre = root;

        // 右
        findModeDiGui(root.r);

    }

}

lc236_二叉树的最近公共祖先

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

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

本题需要从下往上进行查找 也就是回溯 二叉树的回溯过程 也就是下往上 返回给跟节点

后序遍历(左右中)可以根据左右子树的返回值,来处理中节点的逻辑。


题目中 元素是唯一的 而且p q都是一定会存在的 所以

如果递归遍历遇到q,就将q返回,遇到p 就将p返回,那么如果 左右子树的返回值都不为空,说明此时的中节点,一定是q 和p 的最近祖先。

   public Node lowestCommonAncestor(Node root, Node p, Node q) {

        if(root == null || root == p || root == q) return root;

        Node left = lowestCommonAncestor(root.l,p,q);
        Node right = lowestCommonAncestor(root.r, 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 return root;  //找到两个

    }

posted @ 2024-11-21 17:32  小杭呀  阅读(12)  评论(0)    收藏  举报