【堆】——前K个高频元素

347. 前K个高频元素

题目难度:中等

相关标签:[此处可根据实际相关标签补充完整,如数组、哈希表、堆、排序等]

相关企业:[可补充涉及考察该知识点的相关企业]

题目描述

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

示例1

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

示例2

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

提示信息

  1. 1 <= nums.length <= 105
  2. k 的取值范围是 [1, 数组中不相同的元素的个数]
  3. 题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的

进阶要求

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

解法一:粗暴排序法(虽然不满足题目时间复杂度要求,但先给出实现思路供参考)

from typing import List


class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        """
        解法一:粗暴排序法

        思路:
        1. 首先使用字典统计每个元素在数组nums中出现的频次。
        2. 然后将字典中的键值对转换为包含元素及其频次的元组形式,并放入一个列表中。
        3. 接着对这个列表按照元素频次进行降序排序(频次高的在前)。
        4. 最后取排序后的列表中的前k个元素的元素部分(即去掉频次信息),作为前k个高频元素返回。

        参数:
        - nums: 输入的整数数组
        - k: 要获取的前k个高频元素的数量

        返回:
        返回一个列表,包含数组nums中出现频率前k高的元素
        """
        # 步骤一:统计每个元素的出现频次
        frequency_dict = {}
        for num in nums:
            if num in frequency_dict:
                frequency_dict[num] += 1
            else:
                frequency_dict[num] = 1

        # 步骤二:将字典转换为包含元素及其频次的元组列表
        frequency_list = [(num, frequency_dict[num]) for num in frequency_dict]

        # 步骤三:按照频次对元组列表进行降序排序
        frequency_list.sort(key=lambda x: x[1], reverse=True)

        # 步骤四:获取前k个高频元素
        result = [frequency_list[i][0] for i in range(k)]

        return result

解法二:最小堆

from typing import List
import heapq


class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        """
        解法二:最小堆

        思路:
        1. 先通过字典统计数组nums中每个元素的出现频次。
        2. 创建一个最小堆,堆中的元素是包含元素及其频次的元组形式。
        3. 遍历统计频次的字典,对于每个元素:
            - 如果最小堆的大小小于k,直接将元素及其频次的元组加入堆中。
            - 如果最小堆的大小等于k,将当前元素的频次与堆顶元素(堆中频次最小的元素)的频次进行比较:
                - 若当前元素频次大于堆顶元素频次,则弹出堆顶元素,再将当前元素及其频次的元组加入堆中。
        4. 最后,将最小堆中的元素依次取出,只取元素部分(去掉频次信息),组成列表作为前k个高频元素返回。

        参数:
        - nums: 输入的整数数组
        - k: 要获取的前k个高频元素的数量

        返回:
        返回一个列表,包含数组nums中出现频率前k高的元素
        """
        # 步骤一:统计每个元素的出现频次
        frequency_dict = {}
        for num in nums:
            if num in frequency_dict:
                frequency_dict[num] += 1
            else:
                frequency_dict[num] = 1

        # 步骤二:构建最小堆
        heap = []
        for num, frequency in frequency_dict.items():
            # 将元素及其频次的元组加入堆中
            heapq.heappush(heap, (frequency, num))
            if len(heap) > k:
                # 如果堆大小超过k,弹出堆顶元素(频次最小的元素)
                heapq.heappop(heap)

        # 步骤三:获取前K个高频元素
        result = []
        for frequency, num in heap:
            result.append(num)

        return result

解法三:桶排序法

from typing import List


class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        """
        解法三:桶排序法

        思路:
        1. 首先使用字典统计数组nums中每个元素的出现频次。
        2. 创建一个桶,桶的数量为数组nums长度加1,桶的下标表示元素的出现频次,桶内存储出现该频次的元素列表。
        3. 遍历统计频次的字典,对于每个元素及其频次:
            - 根据频次获取对应的桶下标,将元素添加到该下标对应的桶中(如果桶为空则先创建一个空列表再添加)。
        4. 从桶的末尾开始倒序遍历桶,只要结果列表中的元素数量小于k:
            - 如果当前桶不为若为空,将桶内的所有元素添加到结果列表中。
        5. 最后,结果列表中存储的就是数组nums中出现频率前k高的元素,将其返回。

        参数:
        - nums: 输入的整数数组
        - k: 要获取的前k个高频元素的数量

        返回:
        返回一个列表,包含数组nums中出现频率前k高的元素
        """
        # 步骤一:统计每个元素的出现频次
        frequency_dict = {}
        for num in nums:
            if num in frequency_dict:
                frequency_dict[num] += 1
            else:
                frequency_dict[num] = 1

        # 步骤二:桶排序
        # 创建桶,桶的数量为数组长度加1,每个桶初始化为空列表
        buckets = [[] for _ in range(len(nums) + 1)]
        for key, frequency in frequency_dict.items():
            # 根据频次将元素放入对应的桶中
            buckets[frequency].append(key)

        # 步骤三:获取前K个高频元素
        result = []
        for i in range(len(buckets) - 1, -1, -1):
            if buckets[i] and len(result) < k:
                result.extend(buckets[i])

        return result

希望通过这些详细注释的代码能让你更清楚地理解每种解法的实现思路哦,如果还有其他疑问,可以随时问呀。

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

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

相关文章

小试银河麒麟系统OCR软件

0 前言 今天在国产电脑上办公&#xff0c;需要从一些PDF文件中复制文字内容&#xff0c;但是这些PDF文件是图片转换生成的&#xff0c;不支持文字选择和复制&#xff0c;除了手工输入&#xff0c;我们还可以使用OCR。 1 什么是OCR OCR &#xff08;Optical Character Recogni…

小程序租赁系统打造便捷租赁体验助力共享经济发展

内容概要 小程序租赁系统是一个极具创新性的解决方案&#xff0c;它通过简化租赁过程&#xff0c;让物品的共享变得便捷流畅。对于那些有闲置物品的用户来说&#xff0c;他们可以轻松发布自己的物品&#xff0c;让其他需要的人快速找到并租借。而对于找东西的人来说&#xff0…

Spring Boot汽车资讯:科技与汽车的新篇章

摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了汽车资讯网站的开发全过程。通过分析汽车资讯网站管理的不足&#xff0c;创建了一个计算机管理汽车资讯网站的方案。文章介绍了汽车资讯网站的系统分析部分&…

【Python绘图】两种绘制混淆矩阵的方式 (ConfusionMatrixDisplay(), imshow()) 以及两种好看的colorbar

在机器学习领域&#xff0c;混淆矩阵是一个评估分类模型性能的重要工具。它不仅展示了模型预测的准确性&#xff0c;还揭示了模型在不同类别上的表现。本文介绍两种在Python中绘制混淆矩阵的方法&#xff1a;ConfusionMatrixDisplay() 和 imshow()&#xff0c;以及两种好看的co…

【Nginx从入门到精通】03 、安装部署-让虚拟机可以联网

文章目录 总结一、配置联网【Minimal 精简版】1.1、查看网络配置1.2、配置ip地址 : 修改配置文件 <font colororange>ifcfg-ens33Stage 1&#xff1a;输入指令Stage 2&#xff1a;修改参数Stage 3&#xff1a;重启网络Stage 4&#xff1a;测试上网 二、配置联网【Everyth…

android studio无法下载,Could not GET xxx, Received status code 400

-- 1. 使用下面的地址代替 原地址: distributionUrlhttps\://services.gradle.org/distributions/gradle-6.5-all.zip 镜像地址: distributionUrlhttps\://downloads.gradle-dn.com/distributions/gradle-6.5-all.zips 上面的已经不好用了 https\://mirrors.cloud.tencent.c…

Cursor安装Windows / Ubuntu

一、安装 1、下载软件 2、安装依赖 #安装fuse sudo apt-get install fuse3、将cursor添加到应用程序列表 sudo mv cursor-0.42.5x86_64.AppImage /opt/cursor.appimage #使用自己版本号替换 sudo chmod x /opt/cursor.appimage #给予可执行权限 sudo nano /usr/share/applic…

2、计算机网络七层封包和解包的过程

计算机网络osi七层模型 1、网络模型总体预览2、数据链路层4、传输层5.应用层 1、网络模型总体预览 图片均来源B站&#xff1a;网络安全收藏家&#xff0c;没有本人作图 2、数据链路层 案例描述&#xff1a;主机A发出一条信息&#xff0c;到路由器A&#xff0c;这里封装目标MAC…

Elastic 和 Red Hat:加速公共部门 AI 和机器学习计划

作者&#xff1a;来自 Elastic Michael Smith 随着公共部门组织适应数据的指数级增长&#xff0c;迫切需要强大、适应性强的解决方案来管理和处理大型复杂数据集。人工智能 (Artificial intelligence - AI) 和机器学习 (machine learning - ML) 已成为政府机构将数据转化为可操…

【蓝桥杯备赛】深秋的苹果

# 4.1.1. 题目解析 要求某个区间内的数字两两相乘的总和想到前缀和&#xff0c;但是这题重点在于两两相乘先硬算&#xff0c;找找规律&#xff1a; 比如要算这串数字的两两相乘的积之和&#xff1a; 1, 2, 3 1*2 1*3 2*3 1*(23) 2*3 前缀和数组&#xff1a; 1 3 6 发现…

迷你游戏作为电子学习中的趋势工具

多年来&#xff0c;电子学习的格局发生了显著变化&#xff0c;引入了新技术和方法&#xff0c;以更有效地吸引学习者。在这些创新中&#xff0c;迷你游戏的使用已成为一种动态趋势。迷你游戏是紧凑而专注的互动活动&#xff0c;越来越多地被整合到电子学习平台中&#xff0c;以…

6.C操作符详解,深入探索操作符与字符串处理

C操作符详解&#xff0c;深入探索操作符与字符串处理 C语言往期系列文章目录 往期回顾&#xff1a; C语言是什么&#xff1f;编程界的‘常青树’&#xff0c;它的辉煌你不可不知VS 2022 社区版C语言的安装教程&#xff0c;不要再卡在下载0B/s啦C语言入门&#xff1a;解锁基础…

无需Photoshop即可在线裁剪和调整图像大小的工具

Bitmind是一个灵活且易于使用的批量图像本地化处理器&#xff0c;经过抓包看&#xff0c;这个工具在浏览器本地运行&#xff0c;不会上传图片到服务器&#xff0c;所以安全性完全有保证。 它可以将图像调整到任何特定尺寸&#xff0c;并在必要时按比例裁剪。 这是一个在线工具…

Flink1.19编译并Standalone模式本地运行

1.首先下载源码 2.本地运行 新建local_conf和local_lib文件夹&#xff0c;并且将编译后的文件放入对应的目录 2.1 启动前参数配置 2.1.2 StandaloneSessionClusterEntrypoint启动参数修改 2.1.3 TaskManagerRunner启动参数修改 和StandaloneSessionClusterEntrypoint一样修改…

【EtherCAT】关于TwinCAT的使用

1.TwinCAT扫描后会出现轴 双击打开parameter 设置跟随误差为FALSE 设置电子齿轮比&#xff0c;转动一圈进360mm 激活配置 右键新建工程 添加标准工程 添加库lib 必须添加才能使用运动指令 POUS找到main 添加变量 编译 登录PLC 未使能 写入值 手动指令

嵌入式八股文

硬件 1.CPU、MPU、MCU、SOC联系与差别 Cpu是一台计算机的运算核心和控制核心。CPU由运算器、控制器和寄存器及实现它们之间联系的数据、控制及状态的总线构成。差不多所有的CPU的运作原理可分为四个阶 段&#xff1a;提取&#xff08;Fetch&#xff09;、解码&#xff08;Dec…

外卖跑腿小程序源码如何满足多样需求?

外卖跑腿平台已经成了当代年轻人的便捷之选&#xff0c;校园中也不例外&#xff0c;那么外卖、跑腿小程序就需要满足用户多样化的需求&#xff0c;而这背后的源码扮演者最重要的角色。 用户类型的多样性 1.对上班族而言&#xff0c;他们希望外卖小程序能够快速下单、准确配送…

【Java语言】异常处理

异常 异常&#xff1a;在Java中程序执行过程中发生不正常行为。异常为多种&#xff0c;有算数异常、数组越界异常、空指针异常等&#xff08;这些是比较常见的异常&#xff09;&#xff1b; 异常的体系结构&#xff1a; 数组越界异常: ArrayIndexOutOfBoundsException。空指…

使用PSpice进行第一个电路的仿真

1、单击【开始】菜单&#xff0c;选择【OrCAD Capture CIS Lite】。 2、单击【File】>【New】>【Project】。 3、①填入Name下面的文本框&#xff08;提示&#xff1a;项目名称不要出现汉字&#xff09;&#xff1b; ②选择【Analog or Mixed A/D】&#xff1b; ③单击【…

深度剖析C++STL:手持list利剑,破除编程重重难题(上)

前言&#xff1a; C 标准模板库&#xff08;STL&#xff09;中的 list 容器是一个双向链表结构&#xff0c;它提供了高效的插入和删除操 作。与 vector 不同&#xff0c;list 中的元素不是连续存储的&#xff0c;因此可以在任何位置高效插入和删除元素&#xff0c;而无需移动其…