Leetcode 剑指 Offer II 060. 前 K 个高频元素

题目难度: 中等

原题链接

今天继续更新 Leetcode 的剑指 Offer(专项突击版)系列, 大家在公众号 算法精选 里回复 剑指offer2 就能看到该系列当前连载的所有文章了, 记得关注哦~

题目描述

给定一个整数数组 nums 和一个整数 k ,请返回其中出现频率前 k 高的元素。可以按 任意顺序 返回答案。

示例 1:

  • 输入: nums = [1,1,1,2,2,3], k = 2
  • 输出: [1,2]

示例 2:

  • 输入: nums = [1], k = 1
  • 输出: [1]

提示:

  • 1 <= nums.length <= 10^5

  • k 的取值范围是 [1, 数组中不相同的元素的个数]

  • 题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的

  • 进阶:所设计算法的时间复杂度 必须 优于 O(n log n) ,其中 n 是数组大小。

题目思考

  1. 可以使用什么数据结构?

解决方案

思路
  • 分析题目, 我们需要做两件事情: 1. 统计元素的出现频率; 2. 获取出现频率前 k 高的元素
  • 对于第一个任务, 我们可以使用一个计数字典来统计
  • 对于第二个任务, 不难发现它和上一道题目Leetcode 剑指 Offer II 059. 数据流中的第 K 大元素非常类似, 只是把第 k 大改成了前 k 大
  • 所以我们仍然可以沿用相同的思路, 只需要稍作改动:
    • 维护一个最小堆存储(元素频率, 元素)
    • 然后遍历计数字典的键值对, 键就是元素, 而值就是其频率
    • 将(元素频率, 元素)直接加入堆中, 加入后如果堆中元素超过了 k, 就把堆顶弹出
    • 由于是最小堆, 在遍历结束时, 堆中元素正是出现频率最高的 k 个元素及其频率, 更低的都被弹出去了
    • 我们只需要提取出来每个元素, 舍弃其频率, 即为最终结果
  • 下面代码中有详细的注释, 方便大家理解
复杂度
  • 时间复杂度 O(nlogk): 统计每个元素出现频率是 O(n), 而获取出现频率前 k 高的元素需要遍历整个数组, 每次添加或弹出都是操作最多 k 个元素的最小堆, 所以整体是 O(nlogk)
  • 空间复杂度 O(n): 计数字典最多存储 n 个元素, 最小堆最多存储 k 个元素, n>=k, 所以整体是 O(n)
代码
class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        # 计数字典+最小堆
        cnts = collections.Counter(nums)
        q = []
        for num, cnt in cnts.items():
            # 将当前[元素频率, 元素]加入最小堆中
            heapq.heappush(q, [cnt, num])
            if len(q) > k:
                # 如果最小堆个数超过了k, 就把堆顶弹出
                heapq.heappop(q)
        # 最终结果提取出堆中[元素频率, 元素]元组的元素部分
        return [num for _, num in q]

大家可以在下面这些地方找到我~😊

我的 GitHub

我的 Leetcode

我的 CSDN

我的知乎专栏

我的头条号

我的牛客网博客

我的公众号: 算法精选, 欢迎大家扫码关注~😊

算法精选 - 微信扫一扫关注我

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

缘分的计算

题目描述&#xff1a; 缘分是一个外国人难以理解的中文名词。大致说来&#xff0c;缘分是一种冥冥中将两人&#xff08;通常是情人&#xff09;结合的力量。仅管这是种迷信&#xff0c;很多人——特别是女生——喜欢去计算它。 不幸的是&#xff0c;644 也是这样。有天&#x…

【linux笔记】top、ps

【linux笔记】top命令 top&#xff08;Table of process&#xff09;是动态变化的。而ps是静态的。 PID — 进程id USER — 进程所有者 PR — 进程优先级 NI — nice值。负值表示高优先级&#xff0c;正值表示低优先级 VIRT — 进程使用的虚拟内存总量&#xff0c;单位kb。VI…

二叉树的最大深度,力扣

目录 题目地址&#xff1a; 题目&#xff1a; 我们直接看题解吧&#xff1a; 快速理解题解小建议&#xff1a; 审题目事例提示&#xff1a; 解题方法&#xff1a; 解题方法分析&#xff1a; 方法1后序遍历&#xff08;DFS&#xff09; 解题分析&#xff1a; 解题思路&#xff1…

启动 Mac 时显示闪烁的问号

启动 Mac 时显示闪烁的问号 如果启动时在 Mac 屏幕上看到闪烁的问号&#xff0c;这意味着你的 Mac 无法找到自身的系统软件。 如果 Mac 启动时出现闪烁的问号且无法继续启动&#xff0c;请尝试以下步骤。 1.通过按住其电源按钮几秒钟来关闭 Mac。 2.按一下电源按钮&#xf…

强化学习5——动态规划初探

动态规划具体指的是在某些复杂问题中&#xff0c;将问题转化为若干个子问题&#xff0c;并在求解每个子问题的过程中保存已经求解的结果&#xff0c;以便后续使用。实际上动态规划更像是一种通用的思路&#xff0c;而不是具体某个算法。 在强化学习中&#xff0c;被用于求解值函…

华为MDC610接口说明

1、MDC610对外功能接口 2、1、MDC610硬件技术规格

前端插件库-VUE3 使用 vue-codemirror 插件

VUE3 插件 vue-codemirror 使用步骤和实例、基于 CodeMirror &#xff0c;适用于 Vue 的 Web 代码编辑器。 第一步&#xff1a;安装 vue-codemirror & codemirror 包 &#xff0c; 以及语言包 npm install codemirror --save npm install vue-codemirror --savenpm insta…

Linux第13步_安装“vim编辑器”及应用介绍

学习“磁盘重新分区”后&#xff0c;嵌入式Linux系统环境搭建进入安装“vim编辑器”这个环节。vim编辑器可以用来修改文件&#xff0c;在后期使用中&#xff0c;会经常用到。 1、安装“vim编辑器” 输入“sudo apt-get install vim回车”&#xff0c;就可以执行安装“vim编辑…

SpringIOC之support模块ContextTypeMatchClassLoader

博主介绍:✌全网粉丝5W+,全栈开发工程师,从事多年软件开发,在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战,博主也曾写过优秀论文,查重率极低,在这方面有丰富的经验✌ 博主作品:《Java项目案例》主要基于SpringBoot+MyBatis/MyBatis-plus+…

【Bootstrap学习 day11】

Bootstrap5字体图标 字体图标是在Web项目中使用的图标字体。 使用字体图标的好处是&#xff0c;可以通过应用CSS color属性来创建任何颜色的图标。此外&#xff0c;要更改图标的大小&#xff0c;只需使用CSS font-size属性即可。 获取字体图标 在网页中包含Bootstrap5图标的最…

opencv图像金字塔

下采样&#xff1a; #include <opencv2/opencv.hpp> #include <iostream>int main() {// 读取图像cv::Mat src cv::imread("C:/Users/10623/Pictures/adf4d0d56444414cbeb809f0933b9214.png");if (src.empty()) {std::cout << "无法加载图像…

【非关系型数据库】Redis概述及安装、命令使用

目录 前瞻 关系型数据库 非关系型数据库 关系型数据库和非关系型数据库区别 数据存储方式不同 扩展方式不同 对事务性的支持不同 非关系型数据库产生背景 总结 Redis简介 什么是Redis Redis具有的优点 Redis使用场景 哪些数据适合放入缓存中&#xff1f; Redis为什…

nodejs01

nodejs作用 Node.js 是一个免费的、开源的、跨平台的 JavaScript 运行时环境&#xff0c;允许开发人员在浏览器之外编写命令行工具和服务器端脚本. 是javascript的一个运行环境&#xff0c;&#xff0c;&#xff0c; nodejs stream 是前端工程化的基础 nodejs可以作为中间层&…

南金研小巧的CAN总线记录仪在冬测中的使用

南金研小巧的CAN总线记录仪在冬测中的使用&#xff1a; 在这里插入图片描述 1.确定需求&#xff1a;在开始使用前&#xff0c;需要明确冬测的具体需求&#xff0c;例如需要记录的CAN总线数据类型、采样率、存储容量等。 2.连接硬件&#xff1a;将小巧的CAN总线记录仪与需要进行…

年终总结——平凡又不平凡的2023

前言 总结不知道该如何写起&#xff0c;也不知该如何建立这一篇文章的大致框架&#xff0c;只知道我的2023大概也就分成两大块罢了。说起2023一整年&#xff0c;只能用平凡而又不平凡来形容&#xff0c;平凡在我依旧没有什么太突出的技术点&#xff0c;专业水平也一直处于龟速…

无痛迁移:图解 Kubernetes 集群升级步骤

本文探究了Kubeadm集群升级工作流程&#xff0c;并以可视化方式展现。着重介绍了控制平面节点和工作节点的升级步骤&#xff0c;涵盖了kubeadm升级、节点清空、kubelet和kubectl升级&#xff0c;以及解除节点封锁的关键步骤。 这个简明扼要的指南可帮助用户理解和执行Kubernete…

计算机Java项目|基于Springboot实现患者管理系统

作者主页&#xff1a;编程指南针 作者简介&#xff1a;Java领域优质创作者、CSDN博客专家 、掘金特邀作者、多年架构师设计经验、腾讯课堂常驻讲师 主要内容&#xff1a;Java项目、毕业设计、简历模板、学习资料、面试题库、技术互助 文末获取源码 项目编号&#xff1a;KS-032…

new FormData 同时发送表单 json 以及文件二进制流

需要新增时同时发送表单 json 以及对应的文件即可使用以下方法传参 let formDataParams new FormData(); 首先通过 new FormData&#xff08;&#xff09; 创建你需要最后发送的表单 接着将你的对象 json 存储&#xff0c;注意使用 new Blob 创建大表单转换成 json 格式。以…

交换机04_远程连接

通过远程管理方式连接交换机 1、telnet简介 telnet 是应用层协议 基于传输层TCP协议的&#xff0c;默认端口&#xff1a;23 采用的是明文密码方式 不是很安全&#xff0c;一般用于内网管理。 2、ssh协议简介 ssh 是应用层的协议&#xff0c;基于传输层的TCP协议&#x…

新手小白必了解c语言之字符串函数

本篇介绍字符串库函数为 目录 引言 一&#xff1a;字符串函数的头文件为#include 二&#xff1a;求字符串长度函数 &#xff08;strlen&#xff09; 1.函数介绍 2.函数使用举例 3.模拟实现 三&#xff1a;字符串复制函数(strcpy) 1.函数介绍 2.函数使用举例 3.模…