【数据结构】详解堆排序当中的topk问题(leetcode例题)

文章目录

  • 前言
  • 如何理解topk问题
  • 代码逻辑
  • 代码实现

前言

Leetcode相关题目:215. 数组中的第K个最大元素

如何理解topk问题

**Top K 问题是一个经典的问题,在计算机科学中,它的目标是在一组数据中找到前 K 个最大或最小的元素。**这个问题在许多场景下都很重要,比如搜索引擎的搜索结果排名、数据分析中的热门元素筛选等。
.
在最简单的形式中,给定一个数组(或列表)和一个整数 K,Top K 问题要求返回数组中最大的 K 个元素。例如,如果数组是 [4, 2, 9, 6, 23, 12],而 K = 3,那么答案应该是 [23, 9, 12],因为它们是前三个最大的元素。
.
在C语言中,我们可以使用优先队列(堆)或者快速选择等算法来解决Top K问题。堆是一种特殊的树形数据结构,其中每个父节点的值都大于或等于(对于最大堆)/小于或等于(对于最小堆)其子节点的值。堆排序就是基于堆的排序方法,我们可以利用堆的特性来快速找到最大或最小的元素。

当我们第一次接触这个问题时,我们会想到的方法可能是:

将这个数组建堆,进行堆排序调整为大根堆,然后再取出栈顶的前k个元素就是最大的前k个元素;
可如果我们在这个问题的前提下,再加入几个限制条件:例如
1.改变查找的数据个数——例如:在七千万个数据中找;
2.我们限制程序在执行时的内存空间——让你在1MB的空间里去找这七千万个数据中最大的前十个;

在这两个限制下,我们再去直接使用堆排序是不现实的,所以我们需要用一种更巧妙地方式,但代码的本质上仍然不离开堆排序;

代码逻辑

对于Top K问题,我们首先创建一个最大堆(或最小堆),然后依次将数组中的元素插入堆中。由于堆的性质,每次插入都会保证堆顶元素是最大的。当我们插入 K 个元素后,堆顶的 K 个元素就是我们想要的结果。如果数组中有多个相同的最大元素,堆可能包含多个相同的元素,但这不影响找到前 K 个最大元素。

如果你需要找到最小的 K 个元素,只需在创建堆时使用最小堆即可

解决Top K问题的常见方法主要有以下几种:
. . . .1.堆排序(Heap-based method)这是最常见的方法,使用最大堆(或最小堆)来存储前 K 个元素。首先将所有元素插入堆中,保持堆的性质,然后每次从堆顶取出最大(或最小)元素,将其与数组末尾的元素交换,同时减小堆的大小。重复此过程直到堆的大小为 K。这种方法的时间复杂度为 O(N log K),空间复杂度为 O(K)。

. . . .2.快速选择(QuickSelect):这是一种基于分治的随机化算法,适用于大规模数据。基本思想是选取一个“随机”点,然后根据该点将数组分为两部分,使得左边的所有元素都小于或等于该点,右边的所有元素都大于该点。如果点恰好是第 K 大(或小)的元素,那么就找到了答案。否则,根据点的位置在左子数组或右子数组中递归查找。快速选择的平均时间复杂度为 O(N),但最坏情况下为 O(N^2)。

. . . . 3.计数排序(Counting Sort):当数据范围较小且非负时,可以使用计数排序。通过统计每个元素出现的次数,然后直接得到前 K 个元素。这种方法的时间复杂度为 O(N + K),但要求数据范围知道并且较小。

. . . .4.使用哈希表(Hash-based method):对于特定的问题,如在流式数据中实时找出 Top K 的元素,可以使用哈希表来跟踪最近的 K 个最大值。每当有新数据到来时,检查是否比当前第 K 小的值还大,如果是,则替换掉最小的那个,并更新哈希表。这种方法的时间复杂度取决于哈希表的操作,通常为 O(1) 或 O(log K)。

. . . .5,使用平衡二叉搜索树(Balanced BST):例如AVL树或红黑树,可以在 O(log N) 时间内插入和删除元素,从而找到 Top K 元素。但是,插入和删除操作可能会导致树的不平衡,因此维护平衡性是关键。

在这里我们通过堆排序的方法来讲解topk问题;

代码实现

//使用数组的前k个元素构造含有k个元素的小根堆
//从k+1开始遍历,每次和堆顶元素比较,若被遍历到的元素大于堆顶元素,则替换堆顶元素并调整堆,保证堆内的k个元素总是当前最大的k个元素。
void CreateNDate()
{// 造数据int n = 100000;srand(time(0));const char* file = "data.txt";FILE* fin = fopen(file, "w");if (fin == NULL){perror("fopen error");return;}for (int i = 0; i < n; ++i){int x = (rand()+i) % 10000000;fprintf(fin, "%d\n", x);}fclose(fin);
}void TestHeap3()
{int k;printf("请输入k>:");scanf("%d", &k);int* kminheap = (int*)malloc(sizeof(int) * k);if (kminheap == NULL){perror("malloc fail");return;}const char* file = "data.txt";FILE* fout = fopen(file, "r");if (fout == NULL){perror("fopen error");return;}// 读取文件中前k个数for (int i = 0; i < k; i++){fscanf(fout, "%d", &kminheap[i]);}// 11:51继续// 建K个数的小堆for (int i = (k-1-1)/2; i>=0 ; i--){AdjustDown(kminheap, k, i);}// 读取剩下的N-K个数int x = 0;while (fscanf(fout, "%d", &x) > 0){if (x > kminheap[0]){kminheap[0] = x;AdjustDown(kminheap, k, 0);}}printf("最大前%d个数:", k);for (int i = 0; i < k; i++){printf("%d ", kminheap[i]);}printf("\n");
}

在这段代码中:

1.函数 CreateNDate()
这个函数用于生成包含 100000 个随机整数的数据文件(data.txt)。首先,它设置随机数种子以确保每次运行时生成不同的随机数序列。
使用 srand(time(0)) 设置随机数种子,time(0) 获取当前时间作为随机数源。
定义文件名 file 和尝试打开文件以写入数据,如果失败,输出错误信息并返回。
使用 for 循环生成随机数,并使用 fprintf 将每个数写入文件,每行一个。
最后,关闭文件。

2.函数 TestHeap3()
用户输入要查找的最小值数量 K。
分配一个大小为 K 的整型数组 kminheap 用于存储前 K 个最小值,如果分配失败,输出错误信息并返回。
读取刚刚生成的数据文件(data.txt)中的前 K 个数,存储在 kminheap 中。
对 kminheap 进行堆化操作(从最后一个非叶子节点开始,调用 AdjustDown 函数),使其成为最小堆。
遍历文件中的剩余数字,如果新读取的数字大于堆顶(最小值),则替换堆顶,并再次调整堆,保持堆的性质。
输出找到的前 K 个最小值。

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

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

相关文章

Vue3学习记录第三天

Vue3学习记录第三天 背景说明学习记录Vue3中shallowReactive()和shallowRef()Vue3中toRaw()和markRaw()前端...语法Vue3中readonly()和shallowReadonly()函数前端的防抖 背景 之前把Vue2的基础学了, 这个课程的后面有简单介绍Vue3的部分. 学习知识容易忘, 这里仅简答做一个记录…

【C++进阶】深入STL之 栈与队列:数据结构探索之旅

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ ⏩收录专栏⏪&#xff1a;C “ 登神长阶 ” &#x1f921;往期回顾&#x1f921;&#xff1a;模拟实现list与迭代器 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀stack和queue &#x1f4…

安利一款非常不错浏览器文本翻译插件(效果很不错,值得一试)

官网地址&#xff1a;https://immersivetranslate.com/ “沉浸式翻译”这个词&#xff0c;由我们发明创造。如今&#xff0c;它已然成为“双语对照翻译”的代名词。自2023年上线以来&#xff0c;这款备受赞誉的 AI 双语对照网页翻译扩展&#xff0c;已帮助超过 100 万用户跨越语…

DevOps的原理及应用详解(三)

本系列文章简介: 在当今快速变化的商业环境中,企业对于软件交付的速度、质量和安全性要求日益提高。传统的软件开发和运维模式已经难以满足这些需求,因此,DevOps(Development和Operations的组合)应运而生,成为了解决这些问题的有效方法。 DevOps是一种强调软件开发人员(…

uni-app uni-swipe-action 滑动操作状态恢复

按照uni-app官方文档的写法 当前同一条滑动确认之后 页面列表刷新 但是滑动的状态还在 入下图所示&#xff1a; 我们需要在滑动确认之后 页面刷新 滑动状态恢复 那么我们就来写一下这部分的逻辑&#xff1a; 首先&#xff0c;配置一下:show"isOpened[item.id]" chan…

探地雷达正演模拟,基于时域有限差分方法,二

回顾上一章的内容&#xff0c;首先是探地雷达的使用范围和其主要面向的地球物理勘探对象&#xff0c;其次是Maxwell方程及FDTD基础知识&#xff0c;本章的内容包括&#xff1a;1、基于C的TE波波动方程实现 2、边界问题的产生及处理。 一、基本波动方程实现&#xff1a; 使用C…

SpringBoot的Mybatis-plus实战之基础知识

文章目录 MybatisPlus 介绍一、MyBatisPlus 集成步骤第一步、引入依赖第二步、定义mapper 二、注解TableNameTableldTableField 三、配置文件四、加解密实现步骤 在SpringBoot项目中使用Mybatis-plus&#xff0c;记录下来&#xff0c;方便备查。 MybatisPlus 介绍 为简化开发而…

[数据集][目标检测]厨房积水检测数据集VOC+YOLO格式88张2类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;88 标注数量(xml文件个数)&#xff1a;88 标注数量(txt文件个数)&#xff1a;88 标注类别数…

【Activiti7系列】基于Spring Security的Activiti7工作流管理系统简介及实现(附源码)(下篇)

作者&#xff1a;后端小肥肠 上篇&#xff1a;【Activiti7系列】基于Spring Security的Activiti7工作流管理系统简介及实现&#xff08;上篇&#xff09;_spring security activiti7-CSDN博客 目录 1.前言 2. 核心代码 2.1. 流程定义模型管理 2.1.1. 新增流程定义模型数据 …

Internlm_xcomposer2模型结构解读

Internlm_xcomposer2模型结构解读 项目地址 Internlm_xcomposer2模型总体结构 <class transformers_modules.internlm-xcomposer2-4khd-7b.modeling_internlm_xcomposer2.InternLMXComposer2ForCausalLM> InternLMXComposer2ForCausalLM((model): InternLM2Model((tok_…

阻塞队列和线程池

一、什么是阻塞队列 1.1 什么是队列 队列是先进先出。 队列是一种特殊的线性表&#xff0c;特殊之处在于它只允许在表的前端&#xff08;front&#xff09;进行删除操作&#xff0c;而在表的后端&#xff08;rear&#xff09;进行插入操作&#xff0c;和栈一样&#xff0c;队…

Redis 双写一致原理篇

前言 我们都知道,redis一般的作用是顶在mysql前面做一个"带刀侍卫"的角色,可以缓解mysql的服务压力,但是我们如何保证数据库的数据和redis缓存中的数据的双写一致呢,我们这里先说一遍流程,然后以流程为切入点来谈谈redis和mysql的双写一致性是如何保证的吧 流程 首先…

10.1 Go Goroutine

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

transformer 位置编码源码解读

import torch import mathdef get_positional_encoding(max_len, d_model):"""计算位置编码参数&#xff1a;max_len -- 序列的最大长度d_model -- 位置编码的维度返回&#xff1a;一个形状为 (max_len, d_model) 的位置编码张量"""positional_e…

【机器学习】GPT-4中的机器学习如何塑造人类与AI的新对话

&#x1f680;时空传送门 &#x1f50d;引言&#x1f4d5;GPT-4概述&#x1f339;机器学习在GPT-4中的应用&#x1f686;文本生成与摘要&#x1f388;文献综述与知识图谱构建&#x1f6b2;情感分析与文本分类&#x1f680;搜索引擎优化&#x1f4b4;智能客服与虚拟助手&#x1…

国内外网络安全现状分析

一、国内网络安全现状 1.1 国内网络安全威胁 国内的网络安全威胁主要表现在以下几个方面&#xff1a; 恶意软件&#xff1a;包括计算机病毒、蠕虫、木马和间谍软件等&#xff0c;它们能感染计算机系统、窃取敏感信息或破坏系统功能。网络钓鱼&#xff1a;通过伪装成可信任的…

27-LINUX--I/O复用-poll

一.poll概述 poll是一个多路复用的I/O模型&#xff0c;一个进程监视多个文件描述符&#xff0c;当文件描述符就绪时&#xff0c;poll返回可读并做相应处理。 1.poll的模型 #include <poll.h>struct pollfd {int fd; //文件描述符short events; //事件类型 s…

OpenAI新研究破解GPT-4大脑,分解1600万个特征打开“黑匣子”,Ilya 、Jan Leike也参与了!

6月7日凌晨&#xff0c;OpenAI在官网发布了一个新的研究成果&#xff0c;首次破解GPT-4的神经网络活动。通过改进大规模训练稀疏自动编码器将GPT-4的内部表示分解为 1600 万个特征。而且&#xff0c;前段时间离职的Ilya Sutskever、Jan Leike也是作者之一&#xff01; 这不是破…

公式面试题总结(三)

13.说说你对 BOM 的理解&#xff0c;常见的 BOM 对象你了解哪些&#xff1f; BOM (Browser Object Model)&#xff0c;浏览器对象模型&#xff0c; ⚫ 提供了独立于内容与浏览器窗口进行交互的对象 ⚫ 其作用就是跟浏览器做一些交互效果 ⚫ 比如如何进行页面的后退&…

“螺丝钉“好,还是“杂役“好

本篇中&#xff0c;螺丝钉指代大厂工作&#xff0c;杂役则代表小公司工作。这无疑是一个见仁见智且颇为棘手的问题&#xff0c;需结合自身年龄、所处环境等实际状况来做出抉择。倘若一定要给出个人观点&#xff1a;“刚毕业应选择大厂螺丝钉&#xff0c;这对自身眼界的开阔以及…