前 K 个高频元素问题

news/2024/5/20 9:18:02 标签: 数据结构, 算法, LeetCode, , HashMap

前 K 个高频元素问题

作者:Grey

原文地址:

博客园:前 K 个高频元素问题

CSDN:前 K 个高频元素问题

题目描述

LeetCode 347. Top K Frequent Elements

思路

第一步,针对数组元素封装一个数据结构

public class Node {
    int v;
    int t;
    public Node(int value, int times) {
        v = value;
        t = times;
    }
}

其中v表示数组元素,t表示数组元素出现的次数。

第二步,使用哈希表把每个元素的词频先存一下。其中key是数组元素,valueNode类型,封装了数组元素和次数。

        Map<Integer, Node> freqMap = new HashMap<>();
        for (int n : arr) {
            if (freqMap.containsKey(n)) {
                // 存在就把词频加一
                freqMap.get(n).t++;
            } else {
                // 不存在就新建一个词频
                freqMap.put(n, new Node(n, 1));
            }
        }

第三步,使用一个小根,按词频从小到大。我们需要将这个小根维持在K个高频元素。具体做法如下

如果未超过K个元素,可以入

如果已经到了K个元素了,就看顶的元素出现的次数是否比即将要遍历的元素出现的次数少,如果顶元素出现的次数比即将要遍历的元素少,

说明即将遍历的元素比顶元素更高频,可以替换掉顶元素,将其入

如果已经超过K个元素了,那么弹出元素,让始终保持在K个元素。

第四步,弹出中所有元素,即为前K个高频元素。

完整代码如下:

    public static class Node {
        // 值
        public int v;
        // 次数
        public int t;

        public Node(int value, int times) {
            v = value;
            t = times;
        }
    }

    public static int[] topKFrequent(int[] arr, int k) {
        if (arr == null || arr.length == 0 || arr.length < k) {
            return null;
        }
        Map<Integer, Node> freqMap = new HashMap<>();
        for (int n : arr) {
            if (freqMap.containsKey(n)) {
                freqMap.get(n).t++;
            } else {
                freqMap.put(n, new Node(n, 1));
            }
        }
        // 字符种类没有k个,无法得到结果
        if (freqMap.size() < k) {
            return null;
        }
        int[] ans = new int[k];
        PriorityQueue<Node> topK = new PriorityQueue<>(k, Comparator.comparingInt(o -> o.t));
        for (Map.Entry<Integer, Node> entry : freqMap.entrySet()) {
            if (topK.size() <= k || topK.peek().t < entry.getValue().t) {
                topK.offer(entry.getValue());
            }
            if (topK.size() > k) {
                topK.poll();
            }
        }
        int i = 0;
        while (!topK.isEmpty()) {
            ans[i++] = topK.poll().v;
        }
        return ans;
    }

更多

算法数据结构笔记


http://www.niftyadmin.cn/n/1647683.html

相关文章

搭建 Django 服务器

搭建 Django 服务器 购买服务器 设置用户和组 win10 打开控制命令面板首页&#xff0c;找到应用–可选功能—找添加功能 — 找openssh&#xff0c;安装找powershell远程登录命令&#xff1a; ssh root公网ip退出exit规避风险&#xff0c;创建一个普通用户创建用户组 groupa…

如何用常数时间插入、删除和获取随机元素

如何用常数时间插入、删除和获取随机元素 作者&#xff1a;Grey 原文地址: 博客园&#xff1a;如何用常数时间插入、删除和获取随机元素 CSDN&#xff1a;如何用常数时间插入、删除和获取随机元素 题目链接 LeetCode 380. Insert Delete GetRandom O(1) 主要思路 因为要…

VSCode使用git管理项目

VSCode使用git管理项目 首先在Windows上安装git&#xff0c;并设置path环境变量 初始化git仓库&#xff1a; git init查看当前用户名及邮箱 git config user.name git config user.email设置/更改用户名和邮箱 git config --global user.name your name git config --global u…

求数据流中的中位数问题

求数据流中的中位数问题 作者&#xff1a;Grey 原文地址: 博客园&#xff1a;求数据流中的中位数问题 CSDN&#xff1a;求数据流中的中位数问题 题目链接 LeetCode 295. Find Median from Data Stream 主要思路 要得到数据流中的中位数&#xff0c;在偶数的情况下&…

C++ stat判断路径是文件还是目录

C stat判断路径是文件还是目录 1 #include <iostream>2 #include <sys/stat.h>3 4 using namespace std;5 6 void foo ( const char* path ) {7 struct stat s;8 if ( stat ( path, &s ) 0 ) {9 if ( s.st_mode & S_IFDIR ) { 10 …

yield生成器

本文链接&#xff1a;https://blog.csdn.net/qq_34246164/article/details/80960363 相同点&#xff1a;都是返回函数执行的结果 不同点&#xff1a;return 在返回结果后结束函数的运行&#xff0c;而yield 则是让函数变成一个生成器&#xff0c;生成器每次产生一个值&#xff…

找到字符串中所有字母异位词

找到字符串中所有字母异位词 作者&#xff1a;Grey 原文地址&#xff1a; 博客园&#xff1a;找到字符串中所有字母异位词 CSDN&#xff1a;找到字符串中所有字母异位词 题目描述 LeetCode 438. 找到字符串中所有字母异位词 主要思路 使用滑动窗口和欠账表的机制&#…

查找元素在list中的位置以及折半查询

问题 查找某个值在list中的位置 解决思路 能够用折半查询的方法解决此问题。 解决&#xff08;Python&#xff09; #! /usr/bin/env python #coding:utf-8#折半查找某个元素在list中的位置def half_search(lst,value,left,right):length len(lst)while left<right:middle …