代码随想录算法训练营第二十一天|530.二叉搜索树的最小绝对差、501.二叉搜索树中的众数、236. 二叉树的最近公共祖先

代码随想录算法训练营第二十一天|530.二叉搜索树的最小绝对差、501.二叉搜索树中的众数、236. 二叉树的最近公共祖先

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

题目链接

问题简述:求出二叉搜索树中两个元素的最小差值。

思考:因为二叉搜索树中序遍历顺序从小到大,所以只需要在中序遍历中,每次求出前后两个元素差值,并在过程中保存最小的一个。

算法思路:定义last用来记录上一个结点值,定义min作为最小的差值,对二叉树进行中序遍历,每次遍历计算当前节点值和上一个节点值的差值,更新最小差值,并更新上一个结点值。最后返回最小差值。

class Solution {
    //记录上个结点值
    int last = Integer.MAX_VALUE;
    //记录最小差值
    int min = Integer.MAX_VALUE;
    public int getMinimumDifference(TreeNode root) {
        if (root == null) return 0;
        //中序遍历
        getMinimumDifference(root.left);
        // 计算当前节点值和上一个节点值的差值,更新最小差值
        min = Math.min(min, Math.abs(root.val - last));
      	//更新上一个结点值
        last = root.val;
        getMinimumDifference(root.right);
        return min;
    }
}

501.二叉搜索树中的众数

题目链接

问题简述:找出二叉搜索树中的众数,且众数可能包含多个。

思考:感觉用map容易些,最后通过了。其实更好可以在遍历中直接找到众数。

map算法思路:将元素遍历,元素值作为key,元素出现的次数作为value,遍历map找出最大的value,最后将最大的value对应的所有key存入数组。

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

class Solution {
  	//定义map
    Map<Integer, Integer> map = new HashMap<>();
    public int[] findMode(TreeNode root) {
        if (root == null) return new int[0];
        findMode(root.left);
      	//元素值作为key,元素出现的次数作为value
        map.put(root.val, map.getOrDefault(root.val, 0) + 1);
        findMode(root.right);

        int max = 0;
        List<Integer> list = new ArrayList<>();
        //遍历map
        for (Map.Entry<Integer, Integer> entry : map.entrySet()){
            if (entry.getValue() > max) max = entry.getValue();
        }
        for (Map.Entry<Integer, Integer> entry : map.entrySet()){
            if (entry.getValue() == max) list.add(entry.getKey());
        }
      	//将list转换为数组
        return list.stream().mapToInt(Integer::intValue).toArray();

    }
}

改进:定义count记录当前数字出现次数,maxcount记录出现的最大次数。用中序遍历,每次判断当前元素与前一个元素值是否相等,如果相等计数器加一;不相等则重制,每次判断count是否等于最大的maxcount,如果相等则加入list,大于maxcount则将list元素清空,再将当前元素加入list。最后更新前一个结点为当前节点。将转换为数组并返回。

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

class Solution {
    //用于记录出现次数
    int count = 0;
    //记录最大出现次数
    int maxcount = 0;
    List<Integer> list = new ArrayList<>();
    //指向前一个结点
    TreeNode pre = null;
    public int[] findMode(TreeNode root) {
        travel(root);
        return list.stream().mapToInt(Integer::intValue).toArray(); 
    }
    //中序遍历二叉树
    public void travel(TreeNode root){
        if (root == null) return;
        travel(root.left);
        //最开始pre为空
        if (pre == null) {
          	//count变为1
            count++;
        }else if (pre.val == root.val) {
            count++;
          	//count重新计数
        }else if (pre.val != root.val) {
            count = 1;
        }

        //如果重数重复出现,则加入list
        if (count == maxcount) list.add(root.val);
        //如果出现数量更多的数字,则清空list,更新maxcount
        if (count > maxcount){
            list.clear();
            list.add(root.val);
            maxcount = count;
        }
      	//更新前一个结点
        pre = root;
        travel(root.right);
        return;
    }
}

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

题目链接

问题简述:找出两个结点的公共祖先,且结点本身也可作为公共祖先。

思考:感觉很难,属于一丁点思路也没有,看了视频差不多懂了,特别是把特殊情况也归类到普通情况了,太巧妙了。

算法思路:进行后续遍历,如果找到结点p或q。返回p或q,否则返回null。如果左右都不为空,则一个含有p一个含有q,返回当前结点,且为公共祖先;如果一个结点存在一个不存在,说明已经找到了一个公共祖先,为结点left或者right。注意如果这个结点本身为公共祖先,则也返回了这个结点,并不需要特殊讨论。最后都没找到则返回null。

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if (root == null) return null;
        if (root == p) return p;
        if (root == q) return q;
        //后序遍历
        TreeNode left = lowestCommonAncestor(root.left, p, q);
        TreeNode right = lowestCommonAncestor(root.right, p, q);
        //如果左右都不为空,则一个含有p一个含有q,返回当前结点,且为公共祖先
        if (left != null && right != null) return root;
        //如果一个结点存在一个不存在,说明已经找到了一个公共祖先,为结点left(如果这个结点本身为公共祖先,则也返回了这个结点,并不需要特殊讨论)
        if (left != null && right == null) return left;
        //如果一个结点存在一个不存在,说明已经找到了一个公共祖先,为结点right
        if (left == null && right != null) return right;
        return null;
    }
} 

感想

啊啊啊啊啊啊啊啊啊啊

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值