【数据结构】---TopK问题

news2024/10/6 10:27:50

 

本文提供用建堆来解决TopK问题的一个思路

N个数中找出最大的或者最小的前k个

假设现从N个数中找最大的前k个

  • ①堆排序,时间复杂度O(N*logN),这N个数排一下序,前k个数就是需要的
  • ②建堆N个数的小堆,HeapPop 9次,就选出来了 N+(k-1) * logN ------->O(K*logN)
  • ③再优化:建k个数的堆来解决?找最大的前k个,建小堆。思路:如果比堆顶要大,则替换堆顶的数据。假设N是10个亿,内存中存不下这些值(10亿个字节就是1G了,而10亿个整数就是4G了,放内存中建立数组是建不出来的,内存不够,即法1法2对于这种情况不适用),这些值在文件中,k是10。

OJ原题

从N个数中找出最小的前k个数

题述:输入整数数组arr,找出其中最小的k个数。例如,输入4、5、1、6、2、7,3这8个数字,则最小的4个数字是1、2、3,4.

示例一:

输入:arr = 【3,2,1】,k = 2

输出:【1,2】或者【2,1】

示例二:

输入:arr = 【0,1,2,1】,k = 1

输出:【0】

思路:

问题一:

在N个数中找最小的前k个数,应该建大堆还是建小堆?答案:大堆,并且建k个数的大堆,这k个数就是最小的前k个数。同理,如果在N个数中找最大的前k个数,应该建小堆。

问题二:

建大堆怎么找最小的前k个数?

大堆特性:堆顶是堆中的最大数,

①、我们先从N个数中随机找k个数建一个大堆(建大堆就需要向下调整法,这里不细讲,之前博客有讲过)

②、将N个数中第k+1个数开始与堆的堆顶比较(因为前k个数据已拷贝到堆中了),如果比堆顶小,就直接替换堆顶替换完一次就用一次向下调整法(因为你用一个更小的数来替换堆顶,那此时堆顶可能不满足大堆了,但它的左右子树满足大堆,就可以用向下调整法,但用向下调整法是为了把刚才比堆顶小的数弄到下面,使堆顶还是堆的最大的一个),那么再次变为大堆,堆顶一定还是最大的,小的数一定会跑到下面,也就是说其他的数在大堆中,都会被最小的前k个数挤出堆中,所以我们从第k+1个数开始一直跟堆中的数据比较到第N个数完事堆中就是最小的前k个数

代码如下:

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

//为了选出最小的前k个数,所以用向下调整法建大堆
void AdjustDown(int* a, int n, int root)
{
	int parent = root;
	int child = parent * 2 + 1;
	while (child < n)
	{
		if (child + 1 < n && a[child] < a[child + 1])
		{//找出左右孩子中大的那一个
			child++;
		}
		if (a[child] > a[parent])
		{//大堆的特性是父节点>孩子节点
			int tmp = a[child];
			a[child] = a[parent];
			a[parent] = tmp;

			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;//谨记向下调整法是在堆顶不满足堆的性质,而左右子树满足堆的性质时用的
		}
	}
}

/*Note: The returned array must be malloced, assume caller calls free()*/

int* getLeastNumbers(int* arr, int arrSize, int k, int* returnSize)
{
	*returnSize = k;
	if (k == 0)
	{
		return NULL;//如果k==0,说明一个数据都不需要,直接返回NULL就可以
	}
	//建立有k个数的数组,用动态开辟
	int* retNum = (int*)malloc(sizeof(int) * k);
	if (retNum == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}
	memcpy(retNum, arr, sizeof(int) * k);//拷贝至动态数组,方便后续操作
	//我只要array数组的前k个,至于包不包含最小的前k个数都无所谓
	
	//数组建大堆(共k个数)
	for (int i = (k - 1 - 1) / 2; i >= 0; i--)
	{
		AdjustDown(retNum, k, i);
	}

	for (int j = k; j < arrSize; j++)
	{//从第k+1个数开始比较,因为前k个数已经拷贝到retNum堆中了
		if (arr[j] < retNum[0])
		{
			retNum[0] = arr[j];
			AdjustDown(retNum, k, 0);
		}
	}

	return retNum;
}

int main()
{
	int arr[13] = { 1,4,6,7,8,34,2,5,67,8,6,7,9 };
	int LeastNumbersize = 0;
	int * tmp = getLeastNumbers(arr, 13, 5, &LeastNumbersize);
	printf("最小的前k个数:");
	for (int i = 0; i < LeastNumbersize; i++)
	{
		printf("%d ", tmp[i]);
	}
	return 0;
}

运行结果(因为题目没要求找出最小的前k个数后排序,如想排序,可以用一下堆排序):

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

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

相关文章

嵌入式工程师常见面试题(持续更新版本)

前言&#xff1a;鄙人于学堂求学十余载&#xff0c;终是要踏足江湖求一寸安身处&#xff01;以前都忙着学习新东西以及做项目&#xff0c;现如今也需要面对找工作的压力。此篇博客是作者准备的嵌入式工程师常见的面试题目汇总&#xff0c;其答案包含网络搜索和作者自己感悟总结…

6月,视频号爆火的账号有哪些?

六月伊始&#xff0c;视频号就借着六一节点上线青少年内容分级功能&#xff0c;让视频号内容及安全管理更精细化。紧接着开展了“特效大拍档”招募活动&#xff0c;激励各垂类头部创作者持续活跃&#xff0c;与他们共建更丰富健康的内容生态。在官方各种活动激励之下&#xff0…

Python语法基础07(文件与异常)

文件 输出文件中的内容 在项目代码同路径下创建一个pi_digits文件 3.14159265358979323846在fileDemo0.py中将其打开&#xff0c;并输出 #用函数open()打开文件&#xff0c;并将对象赋给file,对于open中的文件路径&#xff0c;可以使用相对路径也可以使用绝对路径 with ope…

2023年淘宝天猫内部大额隐藏粉丝福利购店铺优惠券领取入口在哪里怎么找到免费领取淘宝天猫优惠券?

草柴优惠券APP应用市场下载入口 草柴优惠券APP已上架的应用市场&#xff1a;华为应用市场、小米应用市场、OPPO应用市场、VIVO应用市场及百度手机助手&#xff0c;请打开以上应用市场搜索&#xff1a;草柴优惠券&#xff0c;即可下载通过应用市场审核验证通过的安全可信应用&a…

JavaWeb Cookie

1.Cookie 介绍 Cookie是一种用于在Web浏览器和Web服务器之间传递数据的机制。 它是由服务器发送给浏览器的小型文本文件&#xff0c;存储在浏览器的本地计算机上。 浏览器在后续请求中会自动将Cookie发送回服务器&#xff0c;以便服务器可以识别用户并提供个性化的服务。 C…

涨知识,周鸿伟当年踩的坑,如果用这么一个工具就能事半功倍

怎么让员工有效率地工作&#xff1f;如何考核员工&#xff1f;如何让员工有积极的心态&#xff1f;公司的汇报体系应该怎么设计&#xff1f; 这些问题都让360创始人周鸿伟感到困惑&#xff01; 说到“红衣大炮”周鸿伟的本事&#xff0c;那真的不是吹&#xff01; 近期&…

github:网址为 https://github.com/ 的网页可能暂时无法连接,或者它已永久性地移动到了新网址

一、无法访问github 二、尝试ping gitlab.com 三、打开站长工具 查找 ip地址 “www.github.com”A记录/cname检测结果--Dns查询|dns查询--站长工具 四、打开host文件&#xff08;C:\Windows\System32\drivers\etc&#xff09; 20.205.243.166 github.com 五、再次ping github&…

地图制图小技巧_点匹配线方向

目录 目的 实现步骤 功能介绍 功能入口 关键参数 结果 问题延伸 目的 我们在配图的时候&#xff0c;会遇到一种特定的需求&#xff1a;需要对点设置一个风格&#xff0c;并且符号风格自动跟相连或者相交的线保持垂直。 这种是否能够在SuperMap iDesktopX中自动实现呢&#xff0…

直流运算放大电路-----Howland(二)

目录 豪兰德电路形式1 电路图 计算公式 仿真与分析 豪兰德电路形式2 电路图 计算公式 豪兰德电路形式3 电路图 计算公式 改进电路 豪兰德电路形式1 模拟电子技术基础&#xff08;第五版&#xff09;5.7 电路图 计算公式 仿真与分析 如图&#xff0c;红框内为负反馈&…

.net项目开发-EF框架解决添加默认值问题

文章目录 前言EF中核心类DbContextDbContext中的SaveChanges()方法重写SaveChanges()方法注意点-Modified 其它状态下的实体如何操作 前言 最近开发.net项目&#xff0c;持久层用的是EF框架&#xff0c;也是第一次使用这个框架&#xff0c;用这个框架的好处就是基于实体的开发…

【UnityDOTS 小知识】如何通过DOTS修改材质属性以及替换材质与网格

如何通过DOTS修改材质属性以及替换材质与网格 一、DOTS修改材质属性 1.利用 Material Overide Asset Material Overide Asset是一个Unity资产&#xff0c;可以通过Create创建。 创建后指定要修改的材质&#xff0c;以及对应材质的属性&#xff0c;即可完成这个资源创建。 然…

hive关联键 NULL 关联 NULL

结论&#xff1a;关联键 NULL NULL时&#xff0c;不进行关联&#xff0c;即两表关联失败 案例如下&#xff1a; 表A 表B 表A 关联 表B selecta.id as a_id,a.name as a_name,b.id as b_id,b.name as b_name from表A a left join表B b on a.id b.id …

【FFmpeg实战】FFplay音视频同步

作者&#xff1a;Mirs 链接&#xff1a;https://www.jianshu.com/p/d7ead3a5f2bd PTS的由来 音视频同步依赖的一个东西就是pts&#xff08;persentation time stamp &#xff09;显示时间戳 告诉我们该什么时间显示这一帧 ,那么&#xff0c;这个东西是从哪里来的呢&#xff1f…

Jvm创建对象之内存分配-JVM(七)

上篇文章介绍了jvm创建&#xff0c;会校验是否已加载类&#xff0c;没有则加载&#xff0c;通过之前学的源码&#xff0c;classLoader加载完之后&#xff0c;虚拟机开始给类分配内存&#xff0c;指针移动分配和free链表分配&#xff0c;解决并发分配情况用cap和TLAB方法。之后设…

编写LED灯的驱动,创建三个设备文件,每个设备文件和一个LED灯绑定,当操作这个设备文件时只能控制设备文件对应的这盏灯

.编写LED灯的驱动&#xff0c;创建三个设备文件&#xff0c;每个设备文件和一个LED灯绑定&#xff0c;当操作这个设备文件时只能控制设备文件对应的这盏灯 实验现象 test.c #include <stdlib.h> #include <stdio.h> #include <sys/types.h> #include <s…

【linux】使用 sftp 替换 vsftpd

为什么使用 sftp&#xff1f; 1. 基于 ssh 协议&#xff0c;保证数据安全性 2. 大多数防火墙不会阻止 ssh 协议 3. 完全基于文件系统权限对用户进行管理 4. 配置比 vsftpd 简单 另外&#xff0c;我在集成商工作服务于各大甲方&#xff0c;在厦门的一些企业&#xff0c;如&…

一步一步指导如何使用 FastSAM进行图像分割

它以50倍的速度实现了与SAM方法相当的性能。 (SAM) 是一个强大的视觉基础模型,可以根据用户交互提示分割图像中的任何对象。SAM 一经发布就因其准确性而在计算机视觉社区中获得了巨大的关注。然而,SAM 广泛使用计算量大的Transformer (ViT) 架构限制了其实际应用,特别是在…

C# NPOI操作Excel汇总

C#操作Excel有多种方法&#xff0c;如通过数据库的方式来读写Excel的OleDb方式&#xff0c;但是OleDb方式需要安装微软office&#xff0c;还可以通过COM组件方式操作Excel&#xff0c;也需要安装微软Excel。如果不想安装微软办公套餐可以使用ClosedXML、EPPlus、NPOI。本文主要…

【网络系统集成】VLAN实验

1.实验名称:VLAN实验 2.实验目的 在PacketTracer中进行模拟VLAN实验,完成“不同交换机相同VLAN间通讯”实验、“单臂路由”实验与“三层交换实现VLAN间通讯”实验,加深对VLAN间通讯相关知识的理解与掌握。 3.实验内容 3.1不同交换机相同VLAN间通讯 (1)拓扑结构图

STM32——关于时钟源的实际使用及解释

1、STM32内部有5个时钟源&#xff0c;分别为HSI、HSE、LSE、LSI、PLL。 HSE&#xff1a;高速外部时钟&#xff0c;可接石英谐振器、陶瓷谐振器&#xff0c;或者接外部时钟源&#xff0c;其频率范围为4MHZ~16MHZ。 LSE&#xff1a; 低速外部时钟&#xff0c;接频率为32.768KHZ…