难度简单
给你一个含重复值的二叉搜索树(BST)的根节点 root
,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。
如果树中有不止一个众数,可以按 任意顺序 返回。
假定 BST 满足如下定义:
- 结点左子树中所含节点的值 小于等于 当前节点的值
- 结点右子树中所含节点的值 大于等于 当前节点的值
- 左子树和右子树都是二叉搜索树
示例 1:
输入:root = [1,null,2,2] 输出:[2]
示例 2:
输入:root = [0] 输出:[0]
提示:
- 树中节点的数目在范围
[1, 104]
内 -105 <= Node.val <= 105
进阶:你可以不使用额外的空间吗?(假设由递归产生的隐式调用栈的开销不被计算在内)
分析:求出现频率最高的元素集合(可能存在多个总数),看到二叉搜索树马上想到中序遍历有序,使用中序遍历+双指针来解决,用 pre 指针指向前一个节点,cur 指针指向当前节点,比较两个节点的值是否相等。count 为当前统计的频率次数,maxCount为最大频率次数。一共有三种情况,当 pre 指针为空时,当前 cur 指针指向第一个元素count 为 1;当 pre 指针和 cur 指针的值相等时,count++;当 pre 指针 和 cur 指针的值不相等时,count 重新赋值为 1。若count == maxCount就将该元素加入list集合里,若count > maxCount则更新maxCount的值,清空list集合,重新添加当前元素到list集合。
class Solution {
int count = 0; // 统计频率
int maxCount = 0; // 最大频率
TreeNode pre = null;
List<Integer> list = new ArrayList<>();
public int[] findMode(TreeNode root) {
traversal(root);
int[] res = new int[list.size()];
for (int i = 0; i < list.size(); i++){
res[i] = list.get(i);
}
return res;
}
// 二叉搜索树 中序遍历
public void traversal(TreeNode cur){
if (cur == null)
return;
traversal(cur.left); // 左
// 中
if (pre == null){ // 第一个节点
count = 1;
}else if (pre.val == cur.val){ // 与前一个节点值相同
count++;
}else{ // 与前一个节点值不同
count = 1;
}
pre = cur; // 更新前一个节点
if (count == maxCount){ // 若当前统计频率和最大频率相同,放进list中
list.add(cur.val);
}
if (count > maxCount){ // 若当前统计频率大于最大频率
maxCount = count; // 更新最大频率
list.clear(); // 清空list
list.add(cur.val);
}
traversal(cur.right); // 右
return;
}
}
执行结果:
通过
显示详情
添加备注
执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:42.2 MB, 在所有 Java 提交中击败了34.90%的用户
通过测试用例:23 / 23