【算法和数据结构】347、LeetCode前 K 个高频元素

news2024/10/7 16:27:29

文章目录

  • 一、题目
  • 二、解法
  • 三、完整代码

所有的LeetCode题解索引,可以看这篇文章——【算法和数据结构】LeetCode题解。

一、题目

在这里插入图片描述

二、解法

  思路分析:首先我们使用一个哈希表记录每个元素出现的频率。再设置一个优先队列,并将数组中元素出现的频率和该元素依次加入到优先队列。由于优先队列会自动进行排序,所以此时优先队列中存储的值就是按照频率进行排序的。注意排序是按照对组的第一个元素进行,插入优先队列后,对组的first代表元素频率,对组的second代表插入的元素。最后设置一个结果数组,再根据题目中的要求向数组中压入需要的k个最大频率的元素即可。
  程序如下

	vector<int> topKFrequent(vector<int>& nums, int k) {
		unordered_map<int, int> m;
		for (int num : nums) m[num]++;	// 记录元素出现频率,num代表元素,value代表出现的频率
		priority_queue<pair<int, int>> que;			
		for (auto i : m) que.emplace(i.second, i.first);	// 降序排列,大根堆,频次最高的元素在队头
		vector<int> result(k);
		while (!que.empty() && k--) {
			result.emplace_back(que.top().second);
			que.pop();
		}
		return result;
	}

复杂度分析:

  • 时间复杂度: O ( n ∗ l o g n ) O(n*logn) O(nlogn)。记录元素出现频率需要的复杂度为 O ( n ) O(n) O(n),然后遍历频率数组复杂度为 O ( n ) O(n) O(n),其中优先级队列又要插入频率数组,大顶堆的插入操作复杂度为 O ( l o g n ) O(log n) O(logn),最后向结果数组插入k个最大元素,复杂度为 O ( k ) O(k) O(k)。总复杂度为 O ( n + n ∗ l o g n + k ) = O ( n ∗ l o g n ) O(n + n*log n + k)=O(n*logn) O(n+nlogn+k)=O(nlogn)
  • 空间复杂度: O ( n ) O(n) O(n)

  代码优化:这道题的时间复杂度还可以进一步优化。我们首先要意识到目标是最大的K个频率的元素,因此没有必要将所有的元素都插进优先队列当中,仅仅需要插入K个最大出现频率的元素即可。那么需要与已经插入的K个元素进行对比,此时大根堆就不在适用了,找到最小的值就很困难。因此我们使用小根堆,如果插入元素大于堆顶(小根堆,最小元素),那么插入元素,同时弹出堆顶。使用这种方式只需要维护K个元素的优先级队列,插入的次数也仅仅为 O ( l o g k ) O(log k) O(logk),因此总时间复杂度为 O ( n ∗ l o g k ) O(n*logk) O(nlogk)
  程序如下

	vector<int> topKFrequent2(vector<int>& nums, int k) {
		class mycomparison {	// 为小顶堆提供比较函数
		public:
			bool operator()(const pair<int, int>& lhs, const pair<int, int>& rhs) {
				return lhs.second > rhs.second;
			}
		};
		unordered_map<int, int> m;
		for (int num : nums) m[num]++;	// 记录元素出现频率,key/num代表元素,value代表出现的频率
		priority_queue<pair<int, int>, vector<pair<int, int>>, mycomparison> que;
		for (unordered_map<int, int>::iterator it = m.begin(); it != m.end(); it++) {
			que.push(*it);
			if (que.size() > k) { // 如果堆的大小大于了K,则队列弹出,保证堆的大小一直为k
				que.pop();
			}
		}
		vector<int> result(k);		// 向结果数组中插入K个最大元素
		for (int i = k - 1; i >= 0; i--) {
			result[i] = que.top().first;
			que.pop();
		}
		return result;
	}

三、完整代码

# include <iostream>
# include <vector>
# include <unordered_map>
# include <queue>
using namespace std;

class Solution {
public:
	vector<int> topKFrequent(vector<int>& nums, int k) {
		unordered_map<int, int> m;
		for (int num : nums) m[num]++;	// 记录元素出现频率,num代表元素,value代表出现的频率
		priority_queue<pair<int, int>> que;			
		for (auto i : m) que.emplace(i.second, i.first);	// 降序排列,大根堆,频次最高的元素在队头
		vector<int> result(k);
		while (!que.empty() && k--) {
			result.emplace_back(que.top().second);
			que.pop();
		}
		return result;
	}

	vector<int> topKFrequent2(vector<int>& nums, int k) {
		class mycomparison {	// 为小顶堆提供比较函数
		public:
			bool operator()(const pair<int, int>& lhs, const pair<int, int>& rhs) {
				return lhs.second > rhs.second;
			}
		};
		unordered_map<int, int> m;
		for (int num : nums) m[num]++;	// 记录元素出现频率,key/num代表元素,value代表出现的频率
		priority_queue<pair<int, int>, vector<pair<int, int>>, mycomparison> que;
		for (unordered_map<int, int>::iterator it = m.begin(); it != m.end(); it++) {
			que.push(*it);
			if (que.size() > k) { // 如果堆的大小大于了K,则队列弹出,保证堆的大小一直为k
				que.pop();
			}
		}
		vector<int> result(k);		// 向结果数组中插入K个最大元素
		for (int i = k - 1; i >= 0; i--) {
			result[i] = que.top().first;
			que.pop();
		}
		return result;
	}
};

void my_print(vector <int>& v, string msg)
{
	cout << msg << endl;
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
		cout << *it << "  ";
	}
	cout << endl;
}

void VectorGenerator(int* arr, vector<int>& v, int arr_len) {
	for (int i = 0; i < arr_len; ++i) {
		v.push_back(arr[i]);
	}
}

int main(){
	int topK = 2;
	int arr[] = { 1,1,1,2,2,3 };
	int arr_len = sizeof(arr) / sizeof(int);
	vector<int> nums;
	VectorGenerator(arr, nums, arr_len);
	my_print(nums, "目标数组");
	Solution s1;
	vector<int> result = s1.topKFrequent2(nums, topK);
	my_print(result, "频率最高的元素");
	system("pause");
	return 0;
}

end

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

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

相关文章

C语言实现扫雷【经典】

前言   本篇文章要实现的是扫雷游戏&#xff0c;其代码实现与上一篇的三子棋游戏类同&#xff0c;都是在棋盘的基础上&#xff0c;与电脑进行对抗&#xff0c;不同的是&#xff0c;扫雷游戏一开始电脑就已经随机布置好了所有“雷”。 请戳 --->三子棋 扫雷游戏 1. 扫雷游…

【Visual Studio】VTK 显示小球例子,在 Windows 上使用 Visual Studio 配合 Qt 构建 VTK

知识不是单独的&#xff0c;一定是成体系的。更多我的个人总结和相关经验可查阅这个专栏&#xff1a;Visual Studio。 关于更多此例子的资料&#xff0c;可以参考&#xff1a;【Visual Studio】在 Windows 上使用 Visual Studio 配合 Qt 构建 VTK。 文章目录 版本环境VTKTest.…

Nginx upstream 负载均衡配置

[toc] ## 问题: 自7/4 以来, 所有设备同时出现 Network Error, 导致业务无法正常进行, 频率 3次/每分钟; ## 现场情况及原因分析: 3楼: 8条产线 4楼: 20条产线 5楼: 5条产线 点数: 33条线 * 平均 (5台工位 1台电视看板 3台测试仪 ) ≈ 300 - Nginx 日志占用: access 日志 …

【MySQL备份与还原、索引、视图】练习

一、备份与还原 /***************************样例表***************************/CREATE DATABASE booksDB;use booksDB;CREATE TABLE books(bk_id INT NOT NULL PRIMARY KEY,bk_title VARCHAR(50) NOT NULL,copyright YEAR NOT NULL);INSERT INTO booksVALUES (11078, Lear…

UNIX网络编程卷一 学习笔记 第二十三章 高级SCTP套接字编程

SCTP是一个面向消息的协议&#xff0c;递送给用户的是部分的或完整的消息。只有当发送大消息时&#xff0c;在对端才会递送部分的消息。部分消息被递送给应用后&#xff0c;多个部分消息组合成单个完整消息不由SCTP负责。在SCTP应用进程看来&#xff0c;一个消息既可由单个输入…

线性代数的一些小细节

1 .矩阵的满足结合律&#xff0c;但不满足交换律 验证和证明如下图&#xff1a; 如下&#xff0c;UWQ三个矩阵的2种结合&#xff0c;证明矩阵乘法满足结合律 下图中&#xff0c;AB 和BA的值可能是不同的&#xff08;相同的条件是图中相互对应的4项相同&#xff0c;即对称矩阵…

防范 XSS 攻击的措施

防范 XSS 攻击的措施 XSS&#xff08;Cross-site scripting&#xff09;攻击是一种常见的网络安全漏洞&#xff0c;它可以通过注入恶意代码来攻击用户的计算机和浏览器&#xff0c;从而窃取用户的敏感信息或执行恶意操作。本篇文章将介绍防范 XSS 攻击的措施&#xff0c;并提供…

Spring设计模式及部分技术讲解

讲师:邓澎波 Spring面试专题 1.Spring应该很熟悉吧?来介绍下你的Spring的理解 有些同学可能会抢答,不熟悉!!! 好了,不开玩笑,面对这个问题我们应该怎么来回答呢?我们给大家梳理这个几个维度来回答 1.1 Spring的发展历程 先介绍Spring是怎么来的,发展中有哪些核心的节…

Linux文件

目录 系统级I/O 简介 接口 文件描述符fd 重定向 缓冲区 文件系统 软硬链接 动静态库 静态函数库 动态库 系统级I/O 简介 输入/输出&#xff08;I/O&#xff09;是在主存和外部设备&#xff08;磁盘驱动器、终端和网络&#xff09;之间复制数据的过程。输入操作是…

opencv-04 像素处理

opencv-04 像素处理 在 OpenCV 中&#xff0c;最小的数据类型是无符号的 8 位数。因此&#xff0c;在 OpenCV 中&#xff0c;实际上并没有二值图像这种数据类型&#xff0c;二值图像经常是通过处理得到的&#xff0c;然后使用0表示黑色&#xff0c;使用 255 表示白色。 可以将…

【基本算法】三分法模板

洛谷三分法https://www.luogu.com.cn/problem/P3382 题目描述 如题&#xff0c;给出一个 N 次函数&#xff0c;保证在范围 [l,r] 内存在一点 x&#xff0c;使得 [l,x] 上单调增&#xff0c;[x,r] 上单调减。试求出 x 的值。 输入格式 第一行一次包含一个正整数 N 和两个实数…

吐血整理,Jmeter分布式性能压测-常见问题+解决(详细整理)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 安装常见问题 问题…

使用npm和nrm查看源和切换镜像

一、使用npm查看当前源、切换淘宝镜像、切换官方源 &#xff08;1&#xff09;npm查看当前源&#xff1a; npm get registry &#xff08;2&#xff09;npm设置淘宝镜像源&#xff1a; npm config set registry http://registry.npm.taobao.org &#xff08;3&#xff09;n…

注册中心技术Eureka、Nacos

说明&#xff1a;在微服务框架中&#xff0c;各个服务之间都是独立的。理论上来说&#xff0c;各个服务之间是可以直接通信的&#xff0c;但实际上因为服务之间通信需要管理和规划&#xff0c;如请求怎么负载均衡、请求怎么降级处理等等&#xff0c;所以就需要使用一个技术&…

企业绿色发展关键环节:产品碳足迹管理

近年来&#xff0c;产品生产消费对环境造成的影响越来越受到重视。“产品碳足迹”作为衡量产品对环境影响的重要指标&#xff0c;已成为企业在产品生命周期管理中不可忽视的元素。“产品碳足迹”&#xff08;Product Carbon Footprint, PCF&#xff09;是指产品在生产、制造、运…

【剧前爆米花--前端三剑客】JavaScript(WebAPI)中的相关方法和实例

作者&#xff1a;困了电视剧 专栏&#xff1a;《JavaEE初阶》 文章分布&#xff1a;这是一篇关于JavaScript&#xff08;WebAPI&#xff09;的文章&#xff0c;在这篇文章中我会简单介绍一些常用的js方法&#xff0c;并给出他们的应用实例&#xff0c;希望对你有所帮助&#xf…

代码随想录day2 | 977.有序数组的平方 209.长度最小的子数组 59.螺旋矩阵II

文章目录 一、977.有序数组的平方二、209.长度最小的子数组三、59.螺旋矩阵II 一、977.有序数组的平方 977.有序数组的平方 暴力法&#xff1a;O(NlogN) 先所有数字平方&#xff0c;然后再快排&#xff0c;时间复杂度取决于快排 class Solution { public:vector<int> s…

Openlayers实战:加载天地图

国家地理信息公共服务平台“天地图”(以下简称“天地图“)是国家基础地理信息中心建设的网络化地理信息共享与服务门户。 其属于国家队的,有一定的权威性。 在Openlayers中如何加载天地图呢,方法很简单,用XYZ的形式。 它分为底图和标注,可以灵活的做配合使用。 效果图 源…

java学习路程之篇三、知识点、类、模块、项目、操作、下载、安装、IDEA

文章目录 1、IDEA开发工具2、IDEA的下载和安装3、IDEA中的第一个代码4、IDEAZ中的类、模块、项目的操作 1、IDEA开发工具 2、IDEA的下载和安装 3、IDEA中的第一个代码 4、IDEAZ中的类、模块、项目的操作

PX4实战 各种问题的参数调整解决方案

桨叶旋转频率引起的噪声 比较好的震动 不好的震动 一般好的振动特性时&#xff0c;三轴加速度的原始数据值都会在很小的范围内波动&#xff0c;在3范围内就是非常好的振动环境了。 分析飞行器的幅频特性&#xff0c;一方面除了查看飞行器的振动特性好坏&#xff0c;另一方面…