1. 题目描述
给定一个有相同值的二叉搜索树(BST),找出 BST 中的所有众数(出现频率最高的元素)。
假定 BST 有如下定义:
- 结点左子树中所含结点的值小于等于当前结点的值
- 结点右子树中所含结点的值大于等于当前结点的值
- 左子树和右子树都是二叉搜索树
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-mode-in-binary-search-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
2. 示例
3. 思路
要找众数就要比较出现的次数,想要用递归,就想到用全局变量,前后两个全局变量比较,数组存放一个最大的数值,如果两个全局变量相同则扩展数组。递归结束返回结果。
4. 遇上的问题
- 写在原方法里的时候,调用了一个递归,发现全局变量index会没有返回前被再调用的递归覆盖,导致方法实现出错。解决方案是重新,分开了两个递归。一个负责遍历树,找到有几个重复值,一个负责遍历节点,每个节点都调用一个遍历树的递归。太笨了这算法。现在想着都觉得不好,还要再学习啊!
- 测试用例的量一大,夜又深了,脑子就有点跟不上,时间要把握好,题还要多做。
5. 具体实现代码
//index负责寻找树中有多少个重复节点
int index = 0;
//用于记录 保存在数组里的元素在树上出现过几次
int oldSameNum = 0;
//记录返回众数数组
static int arr[] = new int[1];
//系统默认给的方法
public int[] findMode(TreeNode root) {
if(root == null)
return new int[]{};
//调用重载方法
findMode(root,root);
return arr;
}
//两个参数,一个用于遍历左右节点,一个保存根节点,遍历起始点
public int[] findMode(TreeNode node, TreeNode root) {
if(node == null)
return new int[]{};
//调用遍历树的方法,参数分别是根节点以及要对比大小的目标值
initFor(root,node.val);
//遍历完一个节点后就开始比较查看是否为众数
//当Index等于oldSameNum时,表示两个元素出现次数一致,扩展数组。
if(index == oldSameNum){
if (!find(node.val)) {
arr = Arrays.copyOf(arr, arr.length + 1);
arr[arr.length - 1] = node.val;
}
}
//当index>oldSameNum时,表示新查找元素出现次数更多,将其放入数组。
if(index>oldSameNum){
arr= new int[]{node.val};
oldSameNum = index;
}
//将index归0,对左右节点开始遍历。
index = 0;
findMode(node.left,root);
findMode(node.right,root);
return arr;
}
//先序遍历,根左右,并在加上判断节点值是否等于传进来的目标值,
//相等,则index加1
public void initFor(TreeNode root,int val){
if (root==null)
return;
if( (root.val == val)){
index++;
}
initFor(root.left,val);
initFor(root.right,val);
}
//两个全局变量相等的时候
//有可能是 同值不同节点遍历,要排除这种情况。
public boolean find(int val){
for (int i : arr) {
if (i == val)
return true;
}
return false;
}
这种方法真的很不可取,建议原地暴毙,太丑了,还存在重复遍历的可能性真的是令林不舒服,主要是在遍历过程中发现一个现象就是,一个节点值为2的节点,右子节点是4,右子节点的左子节点又是2,这个情况之前没有考虑到。
6. 学习收获,官方一如既往的妙啊
- 官方使用了Morris算法来遍历二叉树,从而让空间复杂度变成了O(1),时间复杂度是O(n),要学习一下Morris算法遍历二叉树才行。
7 题目来源
相信努力把,努力本身就是值得。命运的硕果一直等待着有缘人。------swrici
夜深了,晚安。