力扣347. 前 K 个高频元素(java,最小堆,快速排序法)

Problem: 347. 前 K 个高频元素

文章目录

  • 前言
  • 题目描述
  • 思路
  • 解题方法
  • 复杂度
  • Code

前言

对于求取Top K一般有如下两种题型:

1.针对静态数据(查询TopK操作)
2.针对动态数据(包括添加数据操作和查询TOPK操作)

一般解决思路有如下三种:

1.排序,然后取数组中的第k个元素(一般针对静态数据)
2.利用快速排序算法的思想,做到 O ( n ) O(n) O(n)(一般针对静态数据)
3.利用堆,插入 O ( l o g k ) O(logk) O(logk),获取 O ( 1 ) O(1) O(1)(一般针对动态数据)

题目描述

给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
在这里插入图片描述

思路

思路1:堆

1.维护一个大小为K的小顶堆,当有数据被添加到集合中时,
2.如果堆中的数据个数小于k,我们将新的数据直接插入到小顶堆,
3.如果堆中的数据等于K,我们就拿新添加的数据与堆顶元素比较

3.1. 如果新添加的数据大于堆顶元素,我们就把堆顶元素删除,并且这个新添加的数据插入到堆中;
3.2. 如果新添加的数据小于等于堆顶元素,则不对堆做处理。

即小堆顶中一直都是维护当前数据集合中的Top K,每次询问当前数据的Top K操作就变得比较高效,直接输出小顶堆中的元素即可。

思路2:快速排序

我们先统计出每个元素出现的频率,再以出现频率为基准进行快排

解题方法

解法1:堆

1.创建内部类,便于后面在构建小顶堆时记录每个元素出现与其出现的次数
2.利用HashMap统计每个元素与其出现的次数
3.利用思路中的步骤3维护小顶堆
4.取出k次当前小顶堆的堆顶元素到结果数组中

解法2:快速排序

1.先利用HashMap统计每个元素与其出现的次数
2.将频率字典处理为 List,以便按频率排序
3.编写并执行快速排序,按频率的从高到低排序
4.将前k高频率的元素添加到结果数组并返回

复杂度

堆:
时间复杂度:

O ( n l o g k ) O(nlogk) O(nlogk)

空间复杂度:

O ( n ) O(n) O(n)

快速排序:
时间复杂度:

O ( n l o g n ) O(nlogn) O(nlogn)

空间复杂度:

O ( n ) O(n) O(n)

Code

最小堆代码:

class Solution {private class QElement {int val;int count;public QElement(int val, int count) {this.val = val;this.count = count;}}/*** 利用最小堆维护前K大元素** @param nums 待查询的数组* @param k    整数k* @return     int[]*/public int[] topKFrequent(int[] nums, int k) {//哈希表统计每个数字出现的countMap<Integer, Integer> counts = new HashMap<>();for (int num : nums) {counts.put(num, counts.getOrDefault(num, 0) + 1);}//按照count构建小顶堆PriorityQueue<QElement> minQueue = new PriorityQueue<>(new Comparator<QElement>() {@Overridepublic int compare(QElement o1, QElement o2) {return o1.count - o2.count;}});//求取top kfor (Map.Entry<Integer, Integer> entry : counts.entrySet()) {int key = entry.getKey();int count = entry.getValue();//如果堆中元素的个数小于k,直接加入if (minQueue.size() < k) {minQueue.offer(new QElement(key, count));} else {//如果堆顶元素小于当前数字的频率//则删除原来堆顶元素,重新加入//当前的数字的频率if (minQueue.peek().count < count) {minQueue.poll();minQueue.offer(new QElement(key, count));}}}int[] result = new int[k];for (int i = 0; i < k; ++i) {result[i] = minQueue.poll().val;}return result;}
}

快速排序代码:

class Solution {/*** 求取数组中的频率前K大函数** @param nums 待求取数组* @param k    给定的数字* @return int[]*/public int[] topKFrequent(int[] nums, int k) {if (nums.length == 1) {return new int[]{nums[0]};}/* 以下计算频率 */Map<Integer, Integer> frequentMap = new HashMap<>();for (int num : nums) {frequentMap.put(num, frequentMap.getOrDefault(num, 0) + 1);}int n = frequentMap.size();/* 以下将频率字典处理为 List,以便按频率排序(这里元素类型选择 int[] 而不是 Entry,可以避免后续排序阶段拆箱) */List<int[]> frequentList = new ArrayList<>(n);for (Map.Entry<Integer, Integer> entry : frequentMap.entrySet()) {frequentList.add(new int[]{entry.getKey(), entry.getValue()});}/* 执行快速排序(选择), 注意这里讲频率高的排在前面 */quickSort(frequentList, 0, n - 1);/* 将频率列表中最右边 K 个元素返回即可 */int[] ans = new int[k];for (int i = 0; i < k; i++) {ans[i] = frequentList.get(i)[0];}return ans;}/*** 快速排序函数** @param list  待排序的数组* @param left  待排序数组的左端点* @param right 待排序数组的右端点*/public void quickSort(List<int[]> list, int left, int right) {if (left >= right) {return;}int q = partition(list, left, right);quickSort(list, left, q - 1);quickSort(list, q + 1, right);}/*** 找出数组分区点** @param nums  待分区数组* @param left  待分区数组的左端点* @param right 待分区数组的右端点* @return int*/public int partition(List<int[]> nums, int left, int right) {/* CLRS 中的写法 */int[] pivot = nums.get(right);int i = left - 1;for (int j = left; j < right; j++) {// 频率高的元素排在前面if (nums.get(j)[1] >= pivot[1]) {i++;Collections.swap(nums, i, j);}}Collections.swap(nums, ++i, right);return i;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/184151.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《一带繁花一路歌》趣味化讲述“一带一路”故事,生动化展现“文明互鉴”美好图景

2023年&#xff0c;总台《艺览天下》推出“一带一路”10期特别节目《一带繁花一路歌》&#xff0c;节目邀请“一带一路”沿线国家驻华大使等重量级嘉宾&#xff0c;在地标推介、故事分享、现场互动等环节里趣味化讲述“一带一路”故事&#xff0c;生动地展现出“文明互鉴”的美…

使用Java将yaml转为properties,保证顺序、实测无BUG版本

使用Java将yaml转为properties 一、 前言1.1 顺序错乱的原因1.2 遗漏子节点的原因 二、优化措施三、源码 一、 前言 浏览了一圈网上的版本&#xff0c;大多存在以下问题&#xff1a; 转换后顺序错乱遗漏子节点 基于此进行了优化&#xff0c;如果只是想直接转换&#xff0c;可…

【开源视频联动物联网平台】视频AI智能分析部署方式

利用视频监控的AI智能分析技术&#xff0c;可以让视频监控发挥更大的作用&#xff0c;成为管理者的重要决策工具。近年来&#xff0c;基于视频监控的AI分析算法取得了巨大的发展&#xff0c;并在各种智慧化项目中得到了广泛应用&#xff0c;为客户提供更智能化的解决方案。 然…

【Node.js】笔记整理 3 -npm

写在最前&#xff1a;跟着视频学习只是为了在新手期快速入门。想要学习全面、进阶的知识&#xff0c;需要格外注重实战和官方技术文档&#xff0c;文档建议作为手册使用 系列文章 【Node.js】笔记整理 1 - 基础知识【Node.js】笔记整理 2 - 常用模块【Node.js】笔记整理 3 - n…

Ubuntu22.04 server版本关闭DHCP,手动设置ip

在Ubuntu 22.04 中&#xff0c;网络配置已迁移到 Netplan&#xff0c;因此可以使用 Netplan 配置文件来手动设置 IP 地址并关闭 DHCP。 以下是在 Ubuntu 22.04 上手动设置 IP 地址并禁用 DHCP 的步骤&#xff1a; 打开终端&#xff0c;使用 root 权限或 sudo 执行以下命令&…

WordPress(10)解决中文连接问题

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、修改的前后二、自定义结构讲明三、修改方法前言 提示:这里可以添加本文要记录的大概内容: 1.中文连接如:http://www.lplovemm.love/2023/11/12/测试 2.这种连接在提交sitemap收录的时…

【神经网络】AlexNet

来源 2012年在全球知名的图像识别竞赛 ILSVRC 中&#xff0c;AlexNet 横空出世&#xff0c;直接将错误率降低了近 10 个百分点&#xff0c;这是之前所有机器学习模型无法做到的。 网络结构 AlexNet整体的网络结构包括&#xff1a;1个输入层&#xff08;input layer&#xff…

夸克大模型助力学术科研提效 四大优势提升知识正确性

当严谨的学术科研与创新的大模型技术结合在一起&#xff0c;会擦出什么样的火花&#xff1f;日前&#xff0c;夸克大模型甫一推出便以优秀的性能成为国产大模型中的“学霸”。在中国科学技术协会近期主办的“大模型应用场景研讨会”上&#xff0c;夸克大模型在快速阅读、创作润…

“简洁实用,没有繁琐设置!Cloudreve是个人使用的最佳网盘“

Cloudreve是一款基于Web的文件共享和管理服务软件。它可以用于创建自己的私有云存储服务或公共文件分享平台&#xff0c;该网盘底层支持本机存储、从机存储、阿里云OSS、又拍云、腾讯云COS、七牛云存储、OneDrive&#xff08;国际版/世纪互联版&#xff09;等多种存储方式&…

云轴科技ZStack助力龙芯打造IT产业新生态

11月28日&#xff0c;2023龙芯产品发布暨用户大会在国家会议中心启幕。大会以“到中流击水”为主题&#xff0c;现场发布新一代通用处理器龙芯3A6000、打印机主控芯片龙芯2P0500重磅成果&#xff0c;并对外公布龙芯处理器核IP及龙芯自主指令系统架构授权计划。作为龙芯的卓越行…

如何判断电脑电源质量的好坏?

电脑电源作为电脑的关键部件直接影响到电脑的性能和寿命&#xff0c;因此选择一个好的电源至关重要。那么要如何判断电脑电源的好坏呢?判断的指标都有哪些呢? 1.外观检测 观察电源外观可以初步判断电脑电源的工艺质量和材料质量。外观检测需要检查电源外壳是否坚固&#xff0…

阿里云RDS标准版(x86) vs 经济版(ARM)性能对比

概述 阿里云数据库在去年云栖大会上发布了基于阿里倚天芯片&#xff08;ARM架构&#xff09;的RDS实例&#xff0c;后正式命名为经济版。本文通过标准的sysbench测试&#xff0c;来看看相比与标准版&#xff0c;经济版是否更加“经济”&#xff0c;以帮助开发者选择适合自己的…

《六》CSS 中的自定义属性

自定义属性&#xff1a;也可以称作 CSS 变量或者级联变量&#xff0c;是由 CSS 作者定义的。由自定义属性标记来设定值&#xff08;例如&#xff1a; --main-color: black;&#xff09;&#xff0c;由 var() 函数来获取值&#xff08;例如&#xff1a; color: var(--main-color…

蓝桥杯每日一题2023.11.30

题目描述 九数组分数 - 蓝桥云课 (lanqiao.cn) 题目分析 此题目实际上是使用dfs进行数字确定&#xff0c;每次循环中将当前数字与剩下的数字进行交换 eg.1与2、3、4、、、进行交换 2与3、4、、、进行交换 填空位置将其恢复原来位置即可&#xff0c;也就直接将其交换回去即可…

Golang实践录:读取yaml配置文件

本文对 yaml 文件进行解析。 下载 yaml执行 go get github.com/spf13/viper 安装。 golang 有很多库可以解释 yaml 文件。本文选用 viper 进行解析&#xff0c;执行 go get github.com/spf13/viper 安装。 yaml语法规则 yaml对大小写敏感。yaml的层级关系只能使用空格缩进&a…

Apache httpd-2.4安装并配置转发

目录 一、写在前面二、下载Apache三、编译安装依赖库3.1 编译安装apr3.2 编译安装apr-util3.3 编译安装pcre 四、编译安装及启动Apache4.1 编译安装Apache4.2 启动Apache 五、配置Apache5.1 备份 httpd.conf5.2 启用代理模块5.3 修改监听端口5.4 配置转发规则 六、常用指令6.1 …

Windows核心编程 注册表

目录 注册表概述 打开关闭注册表 创建删除子健 查询写入删除键值 子健和键值的枚举 常用注册表操作 注册表概述 注册表是Windows操作系统、硬件设备以及客户应用程序得以正常运行和保存设置的核心"数据库"&#xff0c;也可以说是一个非常巨大的树状分层结构的…

Docker篇之docker部署harbor仓库

一、首先需要安装docker step1&#xff1a;安装docker #1、安装yun源 yum install -y yum-utils #2、配置yum源 yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo # 如果上面源不稳定的话&#xff0c;更换为下列的aliyun源 yu…

7-2 凯撒密码(生成字母映射字典)

分数 20 作者 python备课组 单位 福州大学至诚学院 凯撒密码是密码学中一种简单且广为人知的加密技术&#xff0c;其本质是将明文中的所有字母按照字母表的顺序向后偏移固定数目后变成密文。例如,当偏移数目为3时&#xff0c;字母a映射成d&#xff0c;字母p映射成s&#xff…

学计算机大学可能会踩得坑!一定要注意!

真希望刚上大学时&#xff0c;就有人能告诉我这个&#xff0c;建议收藏&#xff01; 很多人可能刚进大学时踌躇满志&#xff0c;气吞山河&#xff0c;但却随着时间流逝&#xff0c;慢慢会开始对自己的未来感到迷茫&#xff0c;开始害怕做决定、害怕踩坑&#xff0c;不知道自己该…