本文是力扣LeeCode-LeeCode-501、二叉搜索树中的众数【二叉搜索树+pre辅助节点+DFS】 学习与理解过程,本文仅做学习之用,对本题感兴趣的小伙伴可以出门左拐LeeCode。
给你一个含重复值的二叉搜索树(BST)的根节点 root ,找出并返回 BST 中的所有 众数
(即,出现频率最高的元素)。
如果树中有不止一个众数,可以按 任意顺序 返回。
假定 BST 满足如下定义:
- 结点左子树中所含节点的值 小于等于 当前节点的值
- 结点右子树中所含节点的值 大于等于 当前节点的值
- 左子树和右子树都是二叉搜索树
示例 1:
输入:root = [1,null,2,2]
输出:[2]
示例 2:
输入:root = [0]
输出:[0]
提示:
- 树中节点的数目在范围 [1, 104] 内
- -10^5 <= Node.val <= 10^5
思路
思路一(普通二叉树)
首先这道题要求的是二叉搜索树,如果为我们直接把它当成一颗普通⼆叉树,也是可以直接解决的:遍历存数组+使用map统计频率+最后取高频的一个或者多个数
思路二(二叉搜索树)
既然是搜索树,它中序遍历就是有序的
- 遍历有序数组的元素出现频率,从头遍历,那么⼀定是
相邻两个元素
作⽐较,然后就把出现频率最⾼的元素输出即可 - 出现
相邻两个元素
的情况,可以使⽤pre指针和cur指针的技巧了 - 但需要注意:初始化的时候pre = NULL,实际上比较的是第⼀个元素
统计众数出现次数的代码:
if (pre==null){ // 第⼀个节点
count=1; // 频率为1
} else if (pre.val==cur.val) { // 与前⼀个节点数值相同
count++;
} else{ // 与前⼀个节点数值不同,则复原
count=1;
}
pre = cur; // 更新上⼀个节点
本题要求的是:返回众数集合/数组
1、正常逻辑
:第一遍先找出最⼤频率maxCount,然后重新遍历⼀遍数组把出现频率为maxCount的元素放进众数集合里,最终需要两遍
2、遍历一次数组(只需要遍历⼀遍⼆叉搜索树,就求出了众数的集合)
- maxCount需要最⼤频率的时候保存
- 频率count ⼤于 maxCount的时候,不仅要更新maxCount,⽽且要清空结果集,留着之前的结果集不对
实现代码
class Solution {
TreeNode pre = null;
int count = 0; // 统计频率
int maxCount = 0; // 最⼤频率
List<Integer> resList = new ArrayList<>();
public int[] findMode(TreeNode root) {
searchBST(root);
int[] result = new int[resList.size()];
for (int i=0;i<resList.size();i++){
result[i] = resList.get(i);
}
return result;
}
void searchBST(TreeNode cur){
if (cur==null)return;
searchBST(cur.left); // 左
// 中
if (pre==null){ // 第⼀个节点
count=1;
} else if (pre.val==cur.val) { // 与前⼀个节点数值相同
count++;
} else{ // 与前⼀个节点数值不同
count=1;
}
pre = cur; // 更新上⼀个节点
if (maxCount==count)resList.add(cur.val); // 如果和最⼤值相同,放进resList中
if (count>maxCount){ // 计数⼤于最⼤值频率
maxCount = count; // 更新最⼤频率
resList.clear(); // 很关键的⼀步,不要忘记清空resList,之前resList⾥的元素都失效了
resList.add(cur.val);
}
searchBST(cur.right); // 右
return;
}
}
最重要的一句话:做二叉树的题目,首先需要确认的是遍历顺序
大佬们有更好的方法,请不吝赐教,谢谢