题目大意
给定一个有相同值的二叉搜索树(BST),找出 BST 中的所有众数(出现频率最高的元素)。
假定 BST 有如下定义:
- 结点左子树中所含结点的值小于等于当前结点的值
- 结点右子树中所含结点的值大于等于当前结点的值
- 左子树和右子树都是二叉搜索树
例如:
image.png
提示:如果众数超过1个,不需考虑输出顺序。
进阶:你可以不使用额外的空间吗?(假设由递归产生的隐式调用栈的开销不被计算在内)。
方法一
利用递归遍历的方式遍历树的每个结点,统计每个结点的值出现的次数,并得出最多的次数maxCnt。最后对Map进行一次遍历,找出出现次数等于maxCnt的所有val。
public int[] findMode(TreeNode root) {
HashMap<Integer,Integer> map = new HashMap<>();
PreOrder(root,map);
int maxCnt = -1;
for(Map.Entry<Integer,Integer> entry:map.entrySet())
maxCnt = Math.max(maxCnt,entry.getValue());
ArrayList<Integer> ans = new ArrayList<>();
for(Map.Entry<Integer,Integer> entry:map.entrySet()) {
if(entry.getValue() == maxCnt) ans.add(entry.getKey());
}
return ans.stream().mapToInt(Integer::valueOf).toArray();
}
private void PreOrder(TreeNode root,HashMap<Integer,Integer>map) {
if(root == null) return;
map.put(root.val,map.getOrDefault(root.val,1)+1);
PreOrder(root.left,map);
PreOrder(root.right,map);
}
运行时间16ms,击败9.54%。
方法二
用curTimes和maxTimes动态维护众数的次数。遍历为中序遍历,因为二叉搜素树有大小的顺序关系。
List<Integer> res = new LinkedList<>();
int curTimes = 0;
int maxTimes = 0;
TreeNode pre = null;
public int[] findMode(TreeNode root) {
if(root == null) return new int[]{};
InOrder(root);
return res.stream().mapToInt(Integer::valueOf).toArray();
}
private void InOrder(TreeNode root) {
if(root == null) return;
InOrder(root.left);
if(pre!=null && pre.val == root.val)
curTimes += 1;
else curTimes = 1;
if(curTimes == maxTimes) res.add(root.val);
else if(curTimes>maxTimes) {
res.clear();
res.add(root.val);
maxTimes = curTimes;
}
pre = root;
InOrder(root.right);
}
运行时间6ms,击败34.58%。