代码随想录 day21

验证二叉搜索树

给定一个二叉树,判断其是否是一个有效的二叉搜索树。

假设一个二叉搜索树具有如下特征:

  • 节点的左子树只包含小于当前节点的数。
  • 节点的右子树只包含大于当前节点的数。
  • 所有左子树和右子树自身必须也是二叉搜索树

不能单纯的比较左节点小于中间节点,右节点大于中间节点就完事了

要比较的是 左子树所有节点小于中间节点,右子树所有节点大于中间节点

这个需要定义一个全局遍历,用来比较遍历的节点,是否符合二叉树的特点

代码

代码使用中序遍历,

先找到最左边的叶子节点,赋值给max,然后采用左中右,将这个max(左)和其父节点(中)对比,然后中赋值给max,再去对比右子树

对比过程中,会先找到右子树的最左边的叶子节点来对比这个max,确保符合二叉搜索树

TreeNode max;
public boolean isValidBST(TreeNode root) {
    if (root==null){
        return true;
    }
    // 左
    boolean left = isValidBST(root.left);
    if (!left) {
        return false;
    }
    // 中
    if (max != null && root.val <= max.val) {
        return false;
    }
    max=root;
    // 右
    return isValidBST(root.right);
}

二叉搜索树的最小绝对差

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

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

使用递归法,用一个pre节点记录一下cur节点的前一个节点。因为二叉树是有序的,所以采用左中右的递归遍历时,当前cur节点的val值一定大于前一个pre节点的val值

代码

TreeNode pre;// 记录上一个遍历的结点
int result = Integer.MAX_VALUE;
public int getMinimumDifference(TreeNode root) {
    if(root==null)return 0;
    traversal(root);
    return result;
}
public void traversal(TreeNode root){
    if(root==null)return;
    //左
    traversal(root.left);
    //中
    if(pre!=null){
        result = Math.min(result,root.val-pre.val);
    }
    pre = root;
    //右
    traversal(root.right);
}

二叉搜索树中的众数

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

假定 BST 有如下定义:

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

例如:

输入:root = [1,null,2,2]
输出:[2]
  1. 如果这个树是非二叉搜索树

可以把这个树都遍历了,用map统计频率

把统计的出来的出现频率(即map中的value)排个序

取前面高频的元素

  1. 二叉搜索树,中序遍历就是有序的

用pre记录上一个节点,数值相同,节点肯定是相邻的

使用count记录出现的次数,然后用maxCount记录count的最大值

当maxCount==count时,元素添加到list中

当maxCount<count时,先将list清空,再将次元素添加到list中

代码

public static int[] findMode(TreeNode root) {
    HashMap<Integer, Integer> map = new HashMap<>();
    ArrayList<Integer> list = new ArrayList<>();
    if (root==null) return list.stream().mapToInt(Integer::intValue).toArray();
    //获得二叉树中各个值出现的频率
    search(root,map);
    List<Map.Entry<Integer, Integer>> mapList = map.entrySet().stream()
            .sorted((c1, c2) -> c2.getValue().compareTo(c1.getValue()))
            .collect(Collectors.toList());
    list.add(mapList.get(0).getKey());//频率最高的树
    for (int i = 1; i < mapList.size(); i++) {
        if (mapList.get(i).getValue()==mapList.get(0).getValue()){
            list.add(mapList.get(i).getKey());
        }else {
            break;
        }
    }
    return list.stream().mapToInt(Integer::intValue).toArray();
}

private static void search(TreeNode root, HashMap<Integer, Integer> map) {
    if (root==null) return;
    map.put(root.val,map.getOrDefault(root.val,0)+1);
    search(root.left,map);
    search(root.right,map);
}


//利用二叉树的特点
ArrayList<Integer> list_;
int count;
TreeNode pre;
int maxCount;
public  int[] findMode_(TreeNode root) {
    list_ = new ArrayList<>();
    maxCount = 0;
    count = 0;
    pre = null;
    findMode1_(root);
    return list_.stream().mapToInt(Integer::intValue).toArray();
}

private void findMode1_(TreeNode root) {
    if (root==null) return;
    findMode1_(root.left);
    //中
    if (pre==null||pre.val!= root.val){
        count=1;
    }else {
        count++;
    }
    if (count>maxCount){
        list_.clear();
        list_.add(root.val);
        maxCount=count;
    }else if (count==maxCount){
        list_.add(root.val);
    }
    pre=root;
    findMode1_(root.right);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值