501. 二叉搜索树中的众数

83 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第16天,点击查看活动详情

一、题目描述:

501. 二叉搜索树中的众数

给你一个含重复值的二叉搜索树(BST)的根节点 root ,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。

如果树中有不止一个众数,可以按 任意顺序 返回。

假定 BST 满足如下定义:

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

示例 1:

image.png

输入:root = [1,null,2,2]
输出:[2]

示例 2:

输入:root = [0]
输出:[0]

提示:

  • 树中节点的数目在范围 [1, 10^4] 内
  • -10^5 <= Node.val <= 10^5  

进阶:你可以不使用额外的空间吗?(假设由递归产生的隐式调用栈的开销不被计算在内)

二、思路分析:

  1. BST的中根遍历是有序的
  2. 设置一个变量保存前驱结点,设置一个计数器,记录当前元素出现的次数。
  3. 若前驱结点和当前结点不相等,计数器置为1,若相等则计数器+1
  4. 用一个变量记录当前最大的频率,若当前计数器等于最大频率,将元素加入列表,若大于最评率,列表元素清空,再将当前元素添加进去。(所以可能出现同一元素,多次清空列表再加入列表的情况)
  5. 最后的列表中的元素即为所求的结果,转化为数组即可

三、AC 代码:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    int max = 1;
    int cnt = 0;
    int pre = Integer.MIN_VALUE;

    List<Integer> list = new ArrayList<>();

    public int[] findMode(TreeNode root) {
        inorder(root);
        int[] ans = new int[list.size()];
        for (int i = 0; i < ans.length; i++) {
            ans[i] = list.get(i);
        }
        return ans;
    }

    public void inorder(TreeNode root) {
        if (root == null) return;
        inorder(root.left);
        if (pre == root.val) {
            cnt += 1;
        } else {
            pre = root.val;
            cnt = 1;
        }
        if (max < cnt) {
            list.clear();
            list.add(root.val);
            max = cnt;
        } else if (max == cnt) {
            list.add(root.val);
        }
        inorder(root.right);
    }
}