题目:
给你一个含重复值的二叉搜索树(BST)的根节点 root
,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。
如果树中有不止一个众数,可以按 任意顺序 返回。
假定 BST 满足如下定义:
- 结点左子树中所含节点的值 小于等于 当前节点的值
- 结点右子树中所含节点的值 大于等于 当前节点的值
- 左子树和右子树都是二叉搜索树
思路:中序遍历二叉搜索树可以得到递增序列。
用pre存储前一个便利的节点,root为现在访问的节点 ,count存储现在访问的节点值出现的频率,maxCount存储节点值中最大出现频率,resList存储结果集。
如果pre=null或root.val!=pre.val说明root节点值未出现过,令count=1;否则root节点值以及出现过,count+1。
然后判断count与maxCount的关系。如果count>maxCount,说明resList结果集中存储的结果全都不符合要求,需要清除,把root.val加入结果集,maxCount需要更新为count;如果count=maxCount,则把root.val加入结果集;如果count<maxCount,不需要任何处理。
递归代码:
List<Integer> resList=new ArrayList<>();//结果集
int maxcount=0;//记录最大频率
int count=0;//记录当前节点值出现的频率
TreeNode pre=null;//记录前一个遍历节点
public int[] findMode(TreeNode root) {
find(root);
return resList.stream().mapToInt(Integer::intValue).toArray();
}
public void find(TreeNode root){
if(root==null) return;
find(root.left);
//计数
if(pre==null||root.val!=pre.val)
count=1;
else
count++;
//更新结果以及maxcount
if(count>maxcount){
resList.clear();//最大频率次数改变,之前统计的结果需要全部清除
resList.add(root.val);
maxcount=count;
}
else if(count==maxcount){
resList.add(root.val);
}
pre=root;
find(root.right);
}
注意:返回值为int数组,结果集为List,将List转换为int数组不能直接调用toArray()函数,因为toArray()的返回值为Object数组。借助stream流,将List存储到stream流中在转换为int数组。
迭代代码:
public int[] findMode(TreeNode root) {
List<Integer> resList=new ArrayList<>();//结果集
int maxcount=0;//记录最大频率
int count=0;//记录当前节点值出现的频率
TreeNode pre=null;//记录前一个遍历节点
Stack<TreeNode> stack=new Stack<>();
if(root!=null)
stack.add(root);
while(!stack.isEmpty()){
TreeNode cur=stack.peek();
if(cur!=null){
stack.pop();
if(cur.right!=null) stack.add(cur.right);
stack.add(cur);
stack.add(null);
if(cur.left!=null) stack.add(cur.left);
}
else{
stack.pop();
TreeNode tmp=stack.pop();
//计数
if(pre==null||tmp.val!=pre.val)
count=1;
else count++;
pre=tmp;//更新pre
//更新maxcount与resList
if(count>maxcount){
resList.clear();
maxcount=count;
resList.add(tmp.val);
}
else if(count==maxcount){
resList.add(tmp.val);
}
}
}
return resList.stream().mapToInt(Integer::intValue).toArray();
}