面试题 17.14.最小K个数

news2024/9/23 17:17:02

题目:如下图

答案:如下图

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
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;
		}
		//parent永远不可能为负数,c语言是取整运算(-1)/2=0,
		// 此时parent=child=0,其a[child]=a[parnet],执行break
		if (a[parent] < a[child])
		{
			//交换
			int tmp = a[parent];
			a[parent] = a[child];
			a[child] = tmp;
			//向下进行迭代
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}

//TopK问题,先建大堆,比较,返回
int* smallestK(int* arr, int arrSize, int k, int* returnSize) {
	//判空
	*returnSize = k;
	//开辟返回数组指针
	int* retArr =(int*)malloc(sizeof(int) * k);
	if (k==0)
	{
		return retArr;
	}
	//将arr中的元素复制到retArr中
	for (int i = 0; i < k; ++i)
	{
		retArr[i] = arr[i];
	}
	//向下调整retArr为大堆,并且大堆中的元素个数为k个,第一次见
	for (int i = (k-1-1)/2 ; i>=0; --i)
	{
		//字面意思就行
		//向下调整一调整就是“垂直”的整个路径
		AdjustDown(retArr, k, i);
	}
	//比较并且重新赋值?
	for (int j = k; j < arrSize; ++j)
	{
		if (retArr[0] > arr[j])
		{
			retArr[0] = arr[j];
			AdjustDown(retArr, k, j);
		}
	}

	return retArr;
}

解析:

(1)判空k并且开辟返回数组指针

将k值赋给返回大小指针

题目中要求返回数组指针必须是malloc出来的,这里我们采用malloc函数进行开辟

判空如果k==0,那么我们返回NULL或者retArr(是空指针)都可以
*returnSize = k;
int* retArr =(int*)malloc(sizeof(int) * k);
if (k==0)
{
    return retArr;
}

(2)将arr中的元素拷贝到retArr中

这里利用for循环将有k个值arr数组进行拷贝
for (int i = 0; i < k; ++i)
{
    retArr[i] = arr[i];
}

(3)向下调整retArr为大堆,并且大堆中的元素个数为k个

这里我们采用建大堆而不是小堆是因为:

若采用小堆构建如下图:

第一行是数组,其中k=6,前六个构建一个小堆,如图可知当最小的值1作为堆顶时,最小的k个数的值2比1大无法进入堆中,进而使用小堆进行构建无法进行选出前6个小的元素,故我们采用大堆

采用大堆构建如下图:

显而易见元素作为最小的k个数中的2比堆顶11小那么可以入堆直接覆盖11,调整堆,使用AdjustDown()函数调整数组保持大堆的性质,使其成为大堆


for (int i = (k-1-1)/2 ; i>=0; --i)
{
    //AdjustDown()字面意思就行
    //向下调整一调整就是“侧方垂直”的整个路径

//由于数组的顺序是混乱的没有进行调整,无法保证AdjustDown()函数两侧都是大堆,那么我们在(k-1-1)/2的位置进行调整。k-1的意思是数组末尾的元素,其作为child结点求其parent结点为(k-1-1)/2,
    AdjustDown(retArr, k, i);

(4)AdjustDown()函数的实现

void AdjustDown(int* a,int n,int root)
{
    int parent = root;
    int child = parent * 2 + 1;
    
    while (child<n)
    {

        //默认左孩子是大的,将其与右孩子比较,如果小于右节点则换

这里注意当最后一个结点恰好为左节点会存在没有右孩子的情况,这里我们采用child+1<n进行判断
        if (child + 1 < n && a[child] < a[child + 1])
        {  
            ++child;
        }
        //parent永远不可能为负数,c语言是取整运算(-1)/2=0,
        // 此时parent=child=0,其a[child]=a[parnet],执行break直接跳出循环,故while循环的条件            //为child<n
        if (a[parent] < a[child])
        {
            //交换
            int tmp = a[parent];
            a[parent] = a[child];

            a[child] = tmp;
            //向下进行迭代

            //这里即字面意思AdjustDown向下调整,那么就将child的值赋给parent,重新由父结点计                //算出孩子结点,进而达到向下调整迭代的目的
            parent = child;
            child = parent * 2 + 1;
        }
        else
        {
            break;
        }
    }
}

(5)比较并且重新赋值然后调整数组成为大堆 

令j=k,k为大堆的元素个数同时也为余下数组的第一个数的下标,使j<arrsize进行循环逐渐使最小的k个数进入大堆中去

如果大堆顶retArr[0]大于数组arr[j]那么则直接将arr[j]赋值给retArr[0]中,由于是大堆,那么最小的k个数是一定小于由k个数组成在大堆顶的数,那么其能够进入由k个数组成的大堆(当最小的k个数全部进入大堆中后再也没有数可以进入大堆,因为大堆上的堆顶的数是第k个最小的数,第k+1个小的数>第k个小的数,无法进入大堆),调整数组使其成为大堆

for (int j = k; j < arrSize; ++j)
{
    if (retArr[0] > arr[j])
    {
        retArr[0] = arr[j];

        //AdjustDown()函数由于堆顶两侧都是大堆故是在堆顶进行直接调整
        AdjustDown(retArr, k, j);
    }
}

(6)返回保存有最小的k个数的retArr数组

return retArr;

到这里我们解题完毕

如果对您有帮助的话点一个免费的赞和收藏叭!

由于作者水平不足,如果有任何错误,麻烦读者评论在评论区指点一下,谢谢!

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

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

相关文章

《机器学习》读书笔记:总结“第5章 神经网络”中的概念

&#x1f4a0;神经网络&#xff08;neural network&#xff09; 神经网络是由具有适应性的简单单元组成的广泛并行互联的网络&#xff0c;它的组织能够模拟生物神经系统对真实世界物体所作出的交互反应。 神经网络中最基本的成分是 神经元(neuron / unit)&#xff0c;即上述定…

机械臂泡水维修|机器人雨后进水维修措施

如果机器人不慎被水淹&#xff0c;别慌&#xff01;我们为你准备了一份紧急的机械臂泡水维修抢修指南&#xff0c;帮助你解决这个问题。 【机器人浸水被淹后紧急维修抢修&#xff5c;如何处理&#xff1f;】 机械臂被淹进水后维修处理方式 1. 机械手淹水后断电断网 首先&am…

Hive分布式SQL计算平台

Hive分布式SQL计算平台 一、Hive 概述二、Hive架构三、Hive客户端 1、Hive有哪些客户端可以使用2、Hive第三方客户端 四、Hive使用语法 1、数据库操作2、内部表&#xff0c;外部表3、数据的导入与导出4、分区表5、分桶表6、复杂类型操作7、数据抽样8、Virtual Columns 虚拟列9…

压缩视频大小的方法 怎么减少视频内存大小 几个简单方法

随着4K、8K高清视频的流行&#xff0c;我们越来越容易遇到视频文件体积过大&#xff0c;导致存储空间不足、传输速度缓慢等问题。视频压缩成为解决这一问题的有效途径&#xff0c;但如何在减小文件大小的同时&#xff0c;保证视频质量不受影响呢&#xff1f;本文将为你揭晓答案…

(10)深入理解pandas的核心数据结构:DataFrame高效数据清洗技巧

目录 前言1. DataFrame数据清洗1.1 处理缺失值&#xff08;NaNs&#xff09;1.1.1 数据准备1.1.2 读取数据1.1.3 查找具有 null 值或缺失值的行和列1.1.4 计算每列缺失值的总数1.1.5 删除包含 null 值或缺失值的行1.1.6 利用 .fillna&#xff08;&#xff09; 方法用Portfolio …

OpenCV Mat类简介,Mat对象创建与赋值 C++实现

在 C 中&#xff0c;OpenCV 提供了一个强大的类 Mat 来表示图像和多维矩阵。Mat 类是 OpenCV 中最基础和最常用的类&#xff0c;用于存储和操作图像数据。 文章目录 Mat类简介Mat 类的定义Mat 类的构造函数 代码示例深拷贝示例赋值示例浅拷贝示例 Mat类简介 Mat 类是一个多维…

【雷丰阳-谷粒商城 】【分布式高级篇-微服务架构篇】【29】Sentinel

持续学习&持续更新中… 守破离 【雷丰阳-谷粒商城 】【分布式高级篇-微服务架构篇】【29】Sentinel 简介熔断降级什么是熔断什么是降级相同点不同点 整合Sentinel自定义sentinel流控返回数据使用Sentinel来保护feign远程调用自定义资源给网关整合Sentinel参考 简介 熔断降…

ChatGPT实战100例 - (20) 如何玩转影刀RPA

文章目录 ChatGPT实战100例 - (20) 如何玩转影刀RPA背景需求需求分析与流程设计一、需求收集二、流程梳理三、可行性分析流程设计(详细步骤)具体步骤的影刀RPA实现流程图总结AIGC在影刀RPA中的使用总结其他RPA步骤中可能用到AIGC的地方展望总结ChatGPT实战100例 - (20) 如何玩…

EasyExcel相关

1. easyexcel–100M EasyExcel是一个基于Java的使用简单、节省内存的读写Excel的开源项目。在尽可能节约内存的情况下支持读写百M的Excel。 节省内存的原因&#xff1a;在解析Excel时没有将文件数据一次性全部加载到内存中&#xff0c;而是从磁盘上一行行读取数据&#xff0c…

深度学习之基础知识整理

现在大语言模型很火&#xff0c;但它的基础仍然是以神经网络为基础的深度学习&#xff0c;不懂神经网络&#xff0c;不了解深度学习&#xff0c;对于大语言模型的二次开发也是整不明白。 那到底需要了解哪些知识&#xff1f;才能看懂深度学习/神经网络的基础模型&#xff0c;想…

后端传递中文到前端 乱码问题

后端代码 前端 乱码 decodeURI(name);使用这个方法,这个方法应该是jquery中的方法 这样就不乱码了

Pointnet++改进即插即用系列:全网首发WTConv2d大接受域的小波卷积|即插即用,提升特征提取模块性能

简介:1.该教程提供大量的首发改进的方式,降低上手难度,多种结构改进,助力寻找创新点!2.本篇文章对Pointnet++特征提取模块进行改进,加入WTConv2d,提升性能。3.专栏持续更新,紧随最新的研究内容。 目录 1.理论介绍 2.修改步骤 2.1 步骤一 2.2 步骤二 2.3 步骤三 1.理…

JVM:垃圾回收器演进

文章目录 一、演进二、Shenandoah三、ZGC 一、演进 二、Shenandoah Shenandoah是由Red Hat开发的一款低延迟的垃圾收集器&#xff0c;Shenandoah并发执行大部分GC工作&#xff0c;包括并发的整理&#xff0c;堆大小对STW的时间基本没有影响。 三、ZGC ZGC是一种可扩展的低延…

MySQL数据库基本用法

了解数据库基本概念 什么是数据库&#xff1f; • 长期存放在计算机内&#xff0c;有组织、可共享的大量数据的集合&#xff0c;是一个数据“仓库” MySQL数据库的特点 • 开源免费&#xff0c;小巧但功能齐全 • 可在Windows和Linux系统上运行 • 操作方便&#xff0c;…

VS2019安装MFC组件

VS2019支持的MFC版本是mfc140 ~ mfc142版本&#xff0c;它兼容VS2015、VS2017之前的老版本程序。 一、MFC的历史版本 MFC的历史版本如下&#xff1a; IDE发布时间工具集版本MSC_VERMSVCMFC版本dllVisual C6.01998V601200MSVC6.06.0mfc42.dll、mfcce400.dllVisual Studio 2002…

记录解决springboot项目上传图片到本地,在html里不能回显的问题

项目场景&#xff1a; 项目场景&#xff1a;在我的博客系统里&#xff1a;有个相册模块&#xff1a;需要把图片上传到项目里&#xff0c;在html页面上显示 解决方案 1.建一个文件夹 例如在windows系统下。可以在项目根目录下建个photos文件夹&#xff0c;把上传的图片文件…

[经验] 驰这个汉字的拼音是什么 #学习方法#其他#媒体

驰这个汉字的拼音是什么 驰&#xff0c;是一个常见的汉字&#xff0c;其拼音为“ch”&#xff0c;音调为第四声。它既可以表示动词&#xff0c;也可以表示形容词或副词&#xff0c;意义广泛&#xff0c;经常出现在生活和工作中。下面就让我们一起来了解一下“驰”的含义和用法。…

WSL2 Centos7 Docker服务启动失败怎么办?

wsl 安装的CentOS7镜像,安装了Docker之后,发现用systemctl start docker 无法将docker启动起来。 解决办法 1、编辑文件 vim /usr/lib/systemd/system/docker.service将13行注释掉,然后在下面新增14行的内容。然后保存退出。 2、再次验证 可以发现,我们已经可以正常通过s…

C++笔试练习笔记【3】:Fibonacci数列 WY22

文章目录 Fibonacci数列分析题目代码实现 Fibonacci数列 分析题目 首先我们可以通过三个变量进行移动来形成Fibonacci数列 其次我们通过最前面的变量与N进行比较从而固定数列 之后N和左右两个变量做差取最小值即可 代码实现 #include <iostream> using namespace std;…

pcdn技术如何降低网络延迟

PCDN技术通过以下方式降低网络延迟: 1.动态调度与负载均衡: PCDN通过在CDN的边缘节点上部署代理服务器&#xff0c;能够动态地调度和传输内容。当用户请求内容时&#xff0c; PCDN会根据各个节点的负载情况、距离、传输速度等因素来动态选择最优的节点来提供内容。这种动态调…