题目:
给定一个有相同值的二叉搜索树(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
。如果root
为null
,表示树是空的,即没有任何节点。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;
}
}