二叉搜索树中的众数

来源:https://leetcode-cn.com/problems/find-mode-in-binary-search-tree

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

假定 BST 有如下定义:

结点左子树中所含结点的值小于等于当前结点的值

结点右子树中所含结点的值大于等于当前结点的值

左子树和右子树都是二叉搜索树

例如:

给定 BST [1,null,2,2],

 

 返回[2].

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

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

 

题解:简单的思路是hash解法,根据数值绝对值取模,每次插入查一下存不存在,存在直接加,不存在插入hash节点,这样解需要额外的空间。

那么如何不使用额外的空间?

解法一(hash):

public class 二叉搜索树中的众数501 {

    private long[] head = new long[100010];
    private long[] next = new long[100010];
    private long[] hash = new long[100010];
    private long[] num = new long[100010];
    private long max = -Long.MAX_VALUE;
    private List<Long> vals = new ArrayList<>();
    int MOD = 100010;
    int top = 1;

    private int find(long x){
        for (long i = head[(int)((x<0?-x:x) % MOD)]; i != 0; i = next[(int)i]){
            if(x == hash[(int)i]){
                return (int)i;
            }
        }
        return -1;
    }

    private void add(long x){
        int index = find(x);
        if(index > 0){
            findMax(index, x);
            return;
        }
        int i = (int)((x<0?-x:x) % MOD);
        hash[top] = x;
        next[top] = head[i];
        head[i] = top;
        findMax(top, x);
        top++;
    }

    private void findMax(int top, long x) {
        num[top]++;
        if(num[top] > max){
            vals.clear();
            vals.add(x);
            max = num[top];
        }else if(num[top] == max){
            vals.add(x);
        }
    }

    public void dfs(TreeNode root) {
        if(root == null){
            return;
        }
        add(root.val);
        dfs(root.left);
        dfs(root.right);
    }

    public int[] findMode(TreeNode root) {
        dfs(root);
        int[] answers = new int[vals.size()];
        for(int i = 0; i < vals.size(); i++){
            answers[i] = vals.get(i).intValue();
        }
        return answers;
    }

    public static void main(String[] args) {
        二叉搜索树中的众数501 二叉搜索树中的众数501 = new 二叉搜索树中的众数501();
        二叉搜索树中的众数501.add(1L);
        二叉搜索树中的众数501.add(1L);
    }

} 

解法二:因为该数左孩子一定小于等于根节点,右树一定大于等于根节点,那么中序遍历肯定是有序数列,那么中序遍历时判断连续相等的最大节点数即可

public class 二叉搜索树中的众数501 {

    int maxNum, count;
    long last;
    Set<Long> maxVal = new HashSet<>();
    public void dfs(TreeNode root){
        if(root == null){
            return;
        }
        dfs(root.left);
        findMax(root.val);
        last = root.val;
        dfs(root.right);

    }

    private void findMax(long val) {

        if (maxNum == 0 || val == last){
            count++;
        }else {
            count = 1;
        }

        if(count > maxNum){
            maxNum = count;
            maxVal.clear();
            maxVal.add(val);
        }else if(count == maxNum){
            maxVal.add(val);
        }
    }

    public int[] findMode(TreeNode root) {
        dfs(root);
        int[] answers = new int[maxVal.size()];
        int i = 0;
        for(Long val : maxVal){
            answers[i++] = val.intValue();
        }
        return answers;
    }

    public static void main(String[] args) {
        二叉搜索树中的众数501 二叉搜索树中的众数501 = new 二叉搜索树中的众数501();
        InputUtils.buildMiddle();
        二叉搜索树中的众数501.findMode(InputUtils.head);
    }

}

  

posted @ 2020-09-27 16:20  handsomecui  阅读(196)  评论(0编辑  收藏  举报