代码随想录刷题 240822-二叉搜索树中的众数 lc501

题目:

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

假定 BST 有如下定义:

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

思考:

1. 递归法:需要确定哪三要素? 传入的参数和返回值;终止条件;递归循环的部分

2. 暴力法:用map记录频率

3. 迭代法:只要把中序遍历转成迭代,中间节点的处理逻辑完全一样。

4. 如果不是二叉搜索树,怎么做? 就是普通的二叉树

注意:

返回的是数组,因为有可能有的数字的频率是相同的 所以可能不会返回一个数字

题解

暴力法:

代码:

//暴力法
class Solution {
	public int[] findMode(TreeNode root) {
		Map<Integer, Integer> map = new HashMap<>();//用来记录树中每个节点值出现的频率。键是节点的值,值是该值出现的次数。
		List<Integer> list = new ArrayList<>();//用于存储树中出现频率最高的节点值。
		if (root == null) return list.stream().mapToInt(Integer::intValue).toArray();
		//如果根节点root为空(即树为空),直接返回一个空的整型数组。
		
		// 获得频率 Map。调用searchBST方法遍历整棵树,统计每个节点值的出现频率,并将结果存储在map中。
		searchBST(root, map);
		//将map中的键值对转换为一个List,并按出现频率从高到低进行排序。
		List<Map.Entry<Integer, Integer>> mapList = map.entrySet().stream()
				.sorted((c1, c2) -> c2.getValue().compareTo(c1.getValue()))
				.collect(Collectors.toList());
		//将出现频率最高的节点值加入到list中
		list.add(mapList.get(0).getKey());
		for (int i = 1; i < mapList.size(); i++) {
		//如果当前节点值的出现频率与前一个节点值相同,则将该值加入到list中。
			if (mapList.get(i).getValue() == mapList.get(i - 1).getValue()) {
				list.add(mapList.get(i).getKey());
			} else {
			//如果频率不相同,则跳出循环。
				break;
			}
		}
		return list.stream().mapToInt(Integer::intValue).toArray();
	}

//定义一个辅助方法searchBST,用于递归地遍历二叉搜索树,并记录每个节点值的出现频率。
	void searchBST(TreeNode curr, Map<Integer, Integer> map) {
		if (curr == null) return;
		//更新当前节点值curr.val在map中的频率。如果该值在map中不存在,则默认频率为0。
		map.put(curr.val, map.getOrDefault(curr.val, 0) + 1);
		searchBST(curr.left, map);
		searchBST(curr.right, map);
	}

}
  • if (root == null): 这部分代码检查根节点 root 是否为 null。如果 rootnull,表示树是空的,即没有任何节点。
  • return list.stream().mapToInt(Integer::intValue).toArray();: 如果树为空,直接返回一个空的整型数组。
    • list.stream(): 将 list 转换为一个 Stream(流)。list 是一个空的 ArrayList,因为在代码前面的部分,list 被初始化了,但还没有添加任何元素。
    • mapToInt(Integer::intValue): 这个操作将 Stream<Integer> 转换为 IntStream,这是因为 list 中的元素是 Integer 类型,而最终需要返回的是一个基本类型的 int 数组。这一步会将 Integer 转换为基本类型 int
    • toArray(): 将 IntStream 转换为一个 int[] 数组。因为 list 为空,最终转换后的数组也是空的。

 

统一迭代法:

class Solution {
    public int[] findMode(TreeNode root) {
        int count = 0;
        int maxCount = 0;
        TreeNode pre = null;
        LinkedList<Integer> res = new LinkedList<>();
        Stack<TreeNode> stack = new Stack<>();

        if(root != null)
            stack.add(root);
        
        while(!stack.isEmpty()){
            TreeNode curr = stack.peek();
            if(curr != null){
                stack.pop();
                if(curr.right != null)
                    stack.add(curr.right);
                stack.add(curr);
                stack.add(null);
                if(curr.left != null)
                    stack.add(curr.left);
            }else{
                stack.pop();
                TreeNode temp = stack.pop();
                if(pre == null)
                    count = 1;
                else if(pre != null && pre.val == temp.val)
                    count++;
                else
                    count = 1;
                pre = temp;
                if(count == maxCount)
                    res.add(temp.val);
                if(count > maxCount){
                    maxCount = count;
                    res.clear();
                    res.add(temp.val);
                }
            }
        }
        int[] result = new int[res.size()];
        int i = 0;
        for (int x : res){
            result[i] = x;
            i++;
        }
        return result;    
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值