算法与数据结构-树-简单-二叉搜索树中的众数

二叉搜索树中的众数

题目

leetcode原题:501. 二叉搜索树中的众数

给定一个有相同值的二叉搜索树(BST),找出 BST 中的所有众数(出现频率最高的元素)。

假定 BST 有如下定义:

  • 结点左子树中所含结点的值小于等于当前结点的值
  • 结点右子树中所含结点的值大于等于当前结点的值
  • 左子树和右子树都是二叉搜索树

提示:如果众数超过1个,不需考虑输出顺序

进阶:你可以不使用额外的空间吗?(假设由递归产生的隐式调用栈的开销不被计算在内)

分析

树的题目要求众数,那么求众数的基础就是遍历树+保存中间值,最后返回众数,乍一看蛮简单。但进阶中的需求提到,尽量不使用额外的空间,意思是不使用map能不能做到?

一般来说,解题分为两种思路:

  • 蛮力遍历,保存中间值,通过保存下来的中间值计算输出需要的结果。
  • 通过某种方式使得数据有序,在有序的基础上去思考如何不使用额外空间,仅使用O(1)的空间复杂度来解决问题。

首先思考如何有序遍历

题目有一个特殊的条件,这个树为二叉搜索树,二叉搜索树本身是一定程度有序的,左子树一定小于等于根节点,右子树一定大于等于根节点,那么如何通过遍历让节点有序输出呢?考虑树的三种遍历方式,中序遍历可以实现这个需求!

然后思考如何使用O(1)的空间复杂度来求得众数。

思考到这里,题目就转变为了如果给你一个有序数组,如何使用O(1)空间复杂度求得众数。

考虑一个具体问题:[-1,0,1,1,2,3]

遍历到-1时,众数结果数组为[-1],maxCount=1,依次类推,遍历到第一个1之后,众数数组为[-1,0,1],maxCount依旧为1,接着遍历第二个1,这时发现1的个数为2,大于maxCount,所以需要清空数组,重新把1放进去,并更新maxCount为2,下面的2和3都因为个数小于maxCount不会被加入众数数组中,至此遍历结束。

分析上面的思路,我们需要三个int变量,一个记录了上次遍历数据,一个记录了上次数据的连续个数,另外一个记录了maxCount。

这样大框架就出来了!

总结一下这部分:

  • 中序遍历使得从小到大有序
  • 利用三个int变量记录中间结果,达到O(1)的时间复杂度

代码

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {

    private List<Integer> resultList = new ArrayList<>();
    private int lastNumber;
    private int lastCount;
    private int maxCount;
    
    public int[] findMode(TreeNode root) {
        middleTree(root);

        int[] result = new int[resultList.size()];
        for(int i = 0;i<=resultList.size()-1;i++){
            result[i] = resultList.get(i);
        }
        return result;
    }

    private void middleTree(TreeNode root){
        if(root == null){
            return;
        }
        middleTree(root.left);
        updateList(root.val);
        middleTree(root.right);
    }

    private void updateList(int val){
        if(resultList.size() == 0){
            lastNumber = val;
            lastCount = 1;
            maxCount = 1;
            resultList.add(val);
        }else{
           if(val == lastNumber){
               lastCount++;
           }else{
               lastNumber = val;
               lastCount = 1;
           }

           if(lastCount > maxCount){
              //清空原来list
              resultList.clear();
              //加入
              resultList.add(val);
              //更新maxCount 为 lastCount
              maxCount = lastCount;
           }else if(lastCount == maxCount){
               //加入
               resultList.add(val);
           }else{
               //不加入
           }
        }
    }
}
posted @ 2021-01-11 16:07  Ging  阅读(123)  评论(0编辑  收藏  举报