zoukankan      html  css  js  c++  java
  • Leetcode 501 二叉搜索树中的众树

    Leetcode 501 二叉搜索树中的众树

    数据结构定义:

    给定一个有相同值的二叉搜索树(BST),找出 BST 中的所有众数(出现频率最高的元素)。
    
    假定 BST 有如下定义:
    
    结点左子树中所含结点的值小于等于当前结点的值
    结点右子树中所含结点的值大于等于当前结点的值
    左子树和右子树都是二叉搜索树
    例如:
    给定 BST [1,null,2,2],
    
       1
        
         2
        /
       2
    返回[2].
    
    提示:如果众数超过1个,不需考虑输出顺序
    
    进阶:你可以不使用额外的空间吗?(假设由递归产生的隐式调用栈的开销不被计算在内)
           
     /**
     * Definition for a binary tree node.
     * public class TreeNode {
     * int val;
     * TreeNode left;
     * TreeNode right;
     * TreeNode(int x) { val = x; }
     * }
     */
           
    
    

    运用缓存(未考虑二叉搜索树的特性):

    class Solution {
        private Map<Integer, Integer> cache = new HashMap<>();
    
        public int[] findMode(TreeNode root) {
            getAllCurrentTime(root);
            return getMaxValue();
        }
    
        /*
        * 获取所有节点的出现次数
        */
        private void getAllCurrentTime(TreeNode root) {
            if (root == null) {
                return;
            }
            cache.put(root.val, cache.getOrDefault(root.val, 0) + 1);
            getAllCurrentTime(root.left);
            getAllCurrentTime(root.right);
        }
        
        /*
        * 获取出现次数最大的节点,并返回
        */
        private int[] getMaxValue(){
            List<Integer> temp = new ArrayList<>();
            int max = Integer.MIN_VALUE;
            for (Map.Entry<Integer,Integer> entry : cache.entrySet()) {
                if(entry.getValue() > max)
                    max = entry.getValue();
            }
            for (Map.Entry<Integer,Integer> entry : cache.entrySet()) {
                if(entry.getValue() == max)
                    temp.add(entry.getKey());
            }
            Integer[] array = temp.toArray(new Integer[temp.size()]);
            return  Arrays.stream(array).mapToInt(Integer::valueOf).toArray();
        }
    }
    

    中序遍历方式:

    class Solution {
        private Map<Integer, Integer> inOrderMap = new HashMap<>();
    
        /*
        * 获取最终的数组
        */
        public int[] findMode(TreeNode root) {
            int max = Integer.MIN_VALUE;
            List<Integer> tempList = new ArrayList<>();
            getInOrderTraveral(root);
            for (Map.Entry<Integer, Integer> entry : inOrderMap.entrySet()) {
                if(entry.getValue() > max)
                    max = entry.getValue();
            }
            for (Map.Entry<Integer, Integer> entry : inOrderMap.entrySet()) {
                if(entry.getValue() == max)
                    ((ArrayList) tempList).add(entry.getKey());
            }
            return tempList.stream().mapToInt(Integer::valueOf).toArray();
    
        }
    
        /*
        * 中序遍历获取所有出现次数
        */
        private void getInOrderTraveral(TreeNode root) {
            if (root == null)
                return;
            getInOrderTraveral(root.left);
            inOrderMap.put(root.val, inOrderMap.getOrDefault(root.val, 0) + 1);
            getInOrderTraveral(root.right);
        }
    }
    
    

    中序遍历的优化版:

    class Solution {
        /* 定义存储出现次数最多的临时list*/
        private List<Integer> tempList = new ArrayList<>();
        /*
        * 定义一次遍历时,存储当前状态的参数
        * currentNum: 记录当前的数字
        * count: 记录当前数字重复的次数
        * maxCount: 记录已经扫描过的数字中最大的出现次数
        */
        private int currentNum,count,maxCount;
        public int[] findMode(TreeNode root) {
            inOrderTraveral(root);
            return tempList.stream().mapToInt(Integer::valueOf).toArray();
        }
        private void inOrderTraveral(TreeNode root){
            if(root == null)
                return;
            inOrderTraveral(root.left);
            update(root);
            inOrderTraveral(root.right);
        }
        private void update(TreeNode root){
            //若当前的数字和上一次遍历的数字是一样的,则 count + 1
            if(root.val == currentNum){
                count += 1;
            }else { //否则currentNum 记录当前的数字,count 重新记为 1
                count = 1;
                currentNum = root.val;
            }
            //若当前遍历出现的次数和已经扫描过的数字中最大的出现次数相同,则放入临时list中
            if(count == maxCount){
                tempList.add(root.val);
            }else if(count > maxCount){ //若当前出现的次数大于最大出现次数,则清空list放入当前的节点值
                tempList.clear();
                maxCount = count;
                tempList.add(root.val);
            }
        }
    
    }
    
    

    Morris中序遍历:

    class Solution {
        /*
        * morris遍历可参考 https://www.cnblogs.com/CodingXu-jie/p/13531475.html
        */
        private List<Integer> tempList = new ArrayList<>();
        private int count,currentNum,maxCount;
        public int[] findMode(TreeNode root) {
            if(root == null){
                return new int[0];
            }
            TreeNode cur = root,pre = null;
            while(cur != null){
                if(cur.left == null){
                    update(cur);
                    cur = cur.right;
                    continue;
                }
                pre = cur.left;
                while(pre.right != null && pre.right != cur)
                    pre = pre.right;
                if(pre.right == null){
                    pre.right = cur;
                    cur = cur.left;
                }else{
                    pre.right = null;
                    update(cur);
                    cur = cur.right;
                }
            }
            return tempList.stream().mapToInt(Integer::valueOf).toArray();
        }
    
        private void update(TreeNode root){
            if(root.val == currentNum){
                count += 1;
            }else {
                count = 1;
                currentNum = root.val;
            }
            if(count == maxCount){
                tempList.add(root.val);
            }else if(count > maxCount){
                tempList.clear();
                maxCount = count;
                tempList.add(root.val);
            }
        }
    
    }
    

    参考:

    https://leetcode-cn.com/problems/find-mode-in-binary-search-tree/solution/er-cha-sou-suo-shu-zhong-de-zhong-shu-by-leetcode-/

  • 相关阅读:
    Python基础总结之第三天开始重新认识‘字符串’(新手可相互督促)
    Python基础总结之第二天从变量开始(新手可相互督促)
    Python基础总结之第一天(新手可相互督促)
    简析 Golang IO 包
    简析 Golang net/http 包
    Elasticsearch Query DSL 语言介绍
    Golang Context 包详解
    解读 kubernetes client-go 官方 examples
    ACM学习之路___HDU 1385(带路径保存的 Floyd)
    ACM学习之路___HDU 2066 一个人的旅行
  • 原文地址:https://www.cnblogs.com/CodingXu-jie/p/14096532.html
Copyright © 2011-2022 走看看