11.<tag-二叉树和BST基础>lt.501. 二叉搜索树中的众数

lt.501. 二叉搜索树中的众数

[案例需求]

在这里插入图片描述

[思路分析一, 暴力解法]

  • 我们可以不利用BST的特性, 把它看作是一颗普通的二叉树,
  • 最直观的解法就是遍历整棵树, 把遇到的节点和频度全部记录到map中去,
    • 即 <Integer, Integer> = <二叉树节点的值, 出现的频度>
  • 在添加到map的同时, 我们可以找出每个节点对应频度的最大值.

这个频度最大值, 在我们dfs结束之后, 可以在用map.keySet() 遍历时,
利用get(key) == 最大频度, 找出最大频率对应的节点数, 存入list中即可
再把list转换为数组返回即可;

[代码实现]

//1. 暴力解法
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    int maxFreq = 0;

    public int[] findMode(TreeNode root) {
        // 出现频率最高的元素
        // 中序遍历BST是个升序的序列
        //1. 暴力, 用HashMap记录root.val和出现的次数 <root.val, 次数>
        Map<Integer, Integer> map = new HashMap<>();

        //2. 获得频率map
        dfs(map, root);

        //3. 遍历到最大的频率存入到list
        //int count = 1;

        List<Integer> list = new ArrayList<>();
        for(int key : map.keySet()){
            // if(count < map.get(key)){
            //     list.add(key);
            // }else if(list.size() > 0 && count == map.get(key)
            //      && key != list.get(list.size() - 1)){
            //     list.add(key);
            // }
            
            //目的是为了获取到map中freq最大的, 如果存在相等的最大的, 一起存入即可
            if(map.get(key) == maxFreq){
                list.add(key);
            }
        }

        int[] res = new int[list.size()];
        int index = 0;

        for(int x : list){
            res[index++] = x;
        }

        return res;
    }

    public void dfs(Map<Integer, Integer> map, TreeNode root){
        //2. 递归出口
        if(root == null)return;

        //3. 单层递归逻辑
        dfs(map, root.left);

        map.put(root.val, map.getOrDefault(root.val, 0) + 1);
        //获取到最大的频率
        maxFreq = Math.max(maxFreq, map.getOrDefault(root.val, 0));

        dfs(map, root.right);
    }
}

[思路分析二, DFS, 利用BST性质]

  • 铭记这句话: 对BST中序遍历, 得到的是一个升序的序列
  • 对于本题, 我们利用中序遍历得到升序的序列, 那么重复的数字都是连续的, 我们只需记录下最大的重复次数所对应的数即可。
  • 详细题解: 点我

[代码实现]

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    int maxFreq = 0;
    int count = 0;
    TreeNode pre = null;

    public int[] findMode(TreeNode root) {
        List<Integer> list = new ArrayList<>();
        
        dfs(list, root);

        int[] res = new int[list.size()];
        int index = 0;

        for(int x : list){
            res[index++] = x;
        }

        return res;
    }

    //中序遍历BST, 每次比较前一个节点, 
    //1. 相同记录到count, 在下次不相同时存入list;
    //2. 
    
    public void dfs(List<Integer> list, TreeNode root){
        //1. 递归结束条件
        if(root == null)return;

        dfs(list, root.left); 

        //1. 记录可能的众数
        if(pre == null || pre.val == root.val){
            ++count;
        }else{
            count = 1;
        }

        //2. 将大的众数添加到list,
        // 如果遇见更大的, 清空list, 重新添加
        if(count == maxFreq){
            list.add(root.val);
        }else if(count > maxFreq){
            maxFreq = count;
            list.clear();
            list.add(root.val);
        }
        pre = root;

        dfs(list,root.right);
    }
}
posted @ 2022-05-26 20:28  青松城  阅读(19)  评论(0)    收藏  举报