Leetcode No.501 二叉搜索树中的众数

题目大意

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

  1. 结点左子树中所含结点的值小于等于当前结点的值
  2. 结点右子树中所含结点的值大于等于当前结点的值
  3. 左子树和右子树都是二叉搜索树
    例如:
    image.png

    提示:如果众数超过1个,不需考虑输出顺序。
    进阶:你可以不使用额外的空间吗?(假设由递归产生的隐式调用栈的开销不被计算在内)。

方法一

利用递归遍历的方式遍历树的每个结点,统计每个结点的值出现的次数,并得出最多的次数maxCnt。最后对Map进行一次遍历,找出出现次数等于maxCnt的所有val。

public int[] findMode(TreeNode root) {
        HashMap map = new HashMap<>();
        PreOrder(root,map);

        int maxCnt = -1;
        for(Map.Entry entry:map.entrySet()) 
            maxCnt = Math.max(maxCnt,entry.getValue());
        
        ArrayList ans = new ArrayList<>();
        for(Map.Entry entry:map.entrySet()) {
            if(entry.getValue() == maxCnt) ans.add(entry.getKey());
        }

        return ans.stream().mapToInt(Integer::valueOf).toArray();
    }

    private void PreOrder(TreeNode root,HashMapmap) {
        if(root == null) return;
        map.put(root.val,map.getOrDefault(root.val,1)+1);
        PreOrder(root.left,map);
        PreOrder(root.right,map);
    }

运行时间16ms,击败9.54%。

方法二

用curTimes和maxTimes动态维护众数的次数。遍历为中序遍历,因为二叉搜素树有大小的顺序关系。

List res = new LinkedList<>();
    int curTimes = 0;
    int maxTimes = 0;
    TreeNode pre = null;

    public int[] findMode(TreeNode root) {
         if(root == null) return new int[]{};
         InOrder(root);
         return res.stream().mapToInt(Integer::valueOf).toArray();
     }

     private void InOrder(TreeNode root) {
        if(root == null) return;
        InOrder(root.left);
        if(pre!=null && pre.val == root.val)
            curTimes += 1;
        else curTimes = 1;

        if(curTimes == maxTimes)  res.add(root.val);
        else if(curTimes>maxTimes) {
            res.clear();
            res.add(root.val);
            maxTimes = curTimes;
        }
        pre = root;
        InOrder(root.right);
     }    

运行时间6ms,击败34.58%。

你可能感兴趣的:(Leetcode No.501 二叉搜索树中的众数)