每日算法----寻找二叉搜索树里的众数----2020/09/24

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 题目来源

leetCode


相信努力把,努力本身就是值得。命运的硕果一直等待着有缘人。------swrici
夜深了,晚安。

分治算法是一种基于分治策略的算法,它将问题分解为若干个子问题,然后递归地解决这些子问题,最后将这些子问题的解合并起来得到原问题的解。在求解众数问题时,可以使用分治算法来解决。 众数即为出现次最多的。要求解一个组中的众数,可以将组分为两个部分,分别求出左右两个部分的众数,然后再将两个众数进行比较,选出其中的众数。 分治算法求解众数的步骤如下: 1. 将组分为左右两个部分,分别递归求解左右两个部分的众数。 2. 如果左右两个部分的众数相同,则直接返回这个众数。 3. 如果左右两个部分的众数不同,则统计左右两个部分中各自的众数出现的次,选出次更多的那个作为整个组的众数。 Java代码实现如下: ```java public int majorityElement(int[] nums) { if (nums.length == 1) { return nums[0]; } int mid = nums.length / 2; int[] left = Arrays.copyOfRange(nums, 0, mid); int[] right = Arrays.copyOfRange(nums, mid, nums.length); int leftMajority = majorityElement(left); int rightMajority = majorityElement(right); if (leftMajority == rightMajority) { return leftMajority; } int leftCount = count(nums, leftMajority); int rightCount = count(nums, rightMajority); return leftCount > rightCount ? leftMajority : rightMajority; } private int count(int[] nums, int num) { int count = 0; for (int i = 0; i < nums.length; i++) { if (nums[i] == num) { count++; } } return count; } ``` 这样,就可以使用分治算法来解决众数问题了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值