开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第16天,点击查看活动详情
一、题目描述:
给你一个含重复值的二叉搜索树(BST)的根节点 root ,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。
如果树中有不止一个众数,可以按 任意顺序 返回。
假定 BST 满足如下定义:
- 结点左子树中所含节点的值 小于等于 当前节点的值
- 结点右子树中所含节点的值 大于等于 当前节点的值
- 左子树和右子树都是二叉搜索树
示例 1:
输入:root = [1,null,2,2]
输出:[2]
示例 2:
输入:root = [0]
输出:[0]
提示:
- 树中节点的数目在范围 [1, 10^4] 内
- -10^5 <= Node.val <= 10^5
进阶:你可以不使用额外的空间吗?(假设由递归产生的隐式调用栈的开销不被计算在内)
二、思路分析:
- BST的中根遍历是有序的
- 设置一个变量保存前驱结点,设置一个计数器,记录当前元素出现的次数。
- 若前驱结点和当前结点不相等,计数器置为1,若相等则计数器+1
- 用一个变量记录当前最大的频率,若当前计数器等于最大频率,将元素加入列表,若大于最评率,列表元素清空,再将当前元素添加进去。(所以可能出现同一元素,多次清空列表再加入列表的情况)
- 最后的列表中的元素即为所求的结果,转化为数组即可
三、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);
}
}