拿捏数据结构-top_k问题

news2024/11/18 13:29:20

top_k问题时间复杂度的计算

这里提前说明,时间复杂度的计算的目的是来计算向上调整的更优还是向下调整更优,从肉眼看的话向下调整优于向上调整,接下来我们进行时间复杂度的计算。

此时我们会用到等比数列求和以及裂项相消

如图

首先我们假设求的是满二叉树,我们求节点的个数

满二叉树节点个数

建堆问题:

建堆的话往往的倒数第一个非叶子结点建堆,会时间复杂度最优解:也就是

在构建堆(尤其是二叉堆)时,从最后一个非叶子节点开始进行调整是时间复杂度最优解的原因是,这种方法可以减少不必要的调整操作。

为什么从最后一个非叶子节点开始?

  1. 叶子节点:在完全二叉树中,叶子节点不包含任何子节点,因此不需要进行调整。

  2. 非叶子节点:从最后一个非叶子节点开始,向上逐个进行调整,可以确保每个节点在调整时,其子树已经是堆结构。这样可以减少调整的深度,因为每个节点最多只需要与其子节点交换一次。

  3. 减少调整次数:如果从根节点开始调整,那么每个节点可能需要多次调整才能达到堆的性质,特别是那些位于树底部的节点。而从底部开始,每个节点只需要调整一次即可。

时间复杂度分析

构建堆的过程涉及对每个非叶子节点进行调整。对于一个具有 𝑛n 个节点的完全二叉树:

  • 叶子节点:有 ⌈𝑛/2⌉⌈n/2⌉ 个叶子节点,它们不需要调整。

  • 非叶子节点:有 ⌊𝑛/2⌋⌊n/2⌋ 个非叶子节点,需要进行调整。

对于非叶子节点,从最后一个非叶子节点开始向上调整,每个节点最多只需要进行 log⁡𝑘logk(𝑘k 是节点的深度)次交换。但是,由于树的结构,底部的节点不需要进行多次交换,因此整个调整过程的时间复杂度比 𝑂(𝑛log⁡𝑛)O(nlogn) 要低。

实际上,构建堆的时间复杂度是 𝑂(𝑛)O(n),这是因为:

  • 从最后一个非叶子节点开始,每个节点的调整次数与其深度成反比。

  • 根节点的调整次数最多,但只需要一次。

  • 越往下,节点的深度越小,但需要调整的节点数量越多。

总结

从最后一个非叶子节点开始建堆,可以确保每个节点的调整次数与其深度成反比,从而减少总的调整次数。这种方法利用了完全二叉树的性质,使得整个建堆过程的时间复杂度达到最优,即 𝑂(𝑛)O(n)。这是构建堆的最优策略,因为它最小化了必要的调整操作,从而提高了算法的效率。

建堆复杂度讲解:(向下调整建堆计算)

如图:

这里为什么-2呢,因为我们的向下调整只是调整h-1层,第h层的节点的个数是2^h-1,所以第h-1层自然就是-2

所以我们发现,建堆的时候我们h-1高度的节点的个数相加得出的结果

为T(n)

所以我们进行计算

从而得出时间复杂度,为什么时间复杂度是高度,因为向下调整的时候,我们循环终止条件是循环的高度,也就是当父亲节点不小于sz的时候,所以计算出高度也就计算出了时间复杂度

建堆复杂度讲解:(向上调整建堆计算) 

如图:

计算图解

所以我们得出结论,这里多了n次

对比

向上调整(AdjustUp)和向下调整(AdjustDown)的时间复杂度通常与堆的高度相关,即 log⁡𝑘logk,其中 𝑘k 是堆中元素的数量。然而,在特定情况下,特别是在构建堆的过程中,这些操作的总时间复杂度可以是 𝑂(𝑛)O(n),这里的 𝑛n 是堆中元素的数量。

单个操作的时间复杂度:

  • 向上调整 (AdjustUp):对于单个元素,向上调整的时间复杂度是 𝑂(log⁡𝑘)O(logk),因为它可能需要从叶子节点一直调整到根节点,最多涉及 log⁡𝑘logk 层的比较和交换。

  • 向下调整 (AdjustDown):同样,对于单个元素,向下调整的时间复杂度也是 𝑂(log⁡𝑘)O(logk),因为它可能需要从根节点调整到叶子节点,同样最多涉及 log⁡𝑘logk 层的比较和交换。

构建堆的总时间复杂度:

  • 当我们讨论构建一个包含 𝑛n 个元素的堆时,所有元素的向上调整操作的总时间复杂度是 𝑂(𝑛)O(n)。这是因为:

    • 树的非叶子节点大约是 𝑛/2n/2(因为叶子节点也是 𝑛/2n/2 左右)。

    • 每个非叶子节点的调整操作最多涉及 log⁡𝑘logk 的时间,但是由于树的结构,从根到叶的路径上的节点数量总和大致是 𝑛n。

    • 因此,所有节点的向上调整操作加起来的时间复杂度是 𝑂(𝑛)O(n)。

为什么是 𝑂(𝑛)O(n) 而不是 𝑂(𝑛log⁡𝑘)O(nlogk)?

  • 树的结构特性:在完全二叉树中,每个层级的节点数量是指数增长的。从根节点(1个节点)到第二层(2个节点),再到第三层(4个节点),等等。因此,较低层级的节点数量远多于较高层级的节点数量。

  • 调整深度:根节点的调整可能需要 log⁡𝑘logk 的时间,但较低层级的节点只需要较少的调整时间。由于底部层级的节点数量较多,它们较短的调整时间在总体上对总时间复杂度的贡献较小。

总结:

  • 对于单个元素,向上调整和向下调整的时间复杂度是 𝑂(log⁡𝑘)O(logk)。

  • 在构建堆的过程中,所有元素的向上调整操作的总时间复杂度是 𝑂(𝑛)O(n),而不是 𝑂(𝑛log⁡𝑘)O(nlogk),这是由于完全二叉树的结构特性和调整操作的分布。

因此,向上调整和向下调整在构建堆的过程中的总时间复杂度是 𝑂(𝑛)O(n),而不是 𝑂(log⁡𝑛)O(logn)。这个线性时间复杂度是构建堆算法的一个重要特性,使得它在处理大量数据时非常高效。

向上调整和向下调整虽然最后计算的都是O(N)

但是满二叉树最后一层占据一半的节点

所以我们得出结论,向下调整的复杂度优于向上调整的复杂度

top_k问题的实现逻辑

1,首先我们创建一个文件,写入随机数值1000w个

2,如果需要读取文件里面最大的10个数值,那么我们就需要,创建一个小堆

原因:

这样的话,输入数值的时候,如果读取的数值比堆顶大,就会替换堆顶从而进堆,然后进行堆排序。

3,在读取文件的时候,我们需要读取一个接收一个,然后进行数值的对比,从而进行交换。

4,最后打印最大的数值

5,备注:我们如何判断我们的找到的最大的前十个数值的正确的,

也是很简单的,我们设定的随机数值是10000以内的,然后设定完之后,我们不调用,进入TXT里面更改一些数值。设定一些大于一万的数值,此时我们就可以发现我们筛选的数值对不对。

当然如果我们需要找最小的数值,那么我们设定数值最好为-1,因为十万个数值,很可能是有很多0的。但是我们肉眼看不出来。

top_k计算的代码实现

//进行计算
void TOP_K()
{
	int k = 10;
	//scanf("%d", &k);
	FILE* ps = fopen("data.txt", "r");
	if (ps == NULL)
	{
		perror("Error:opening:file");
		exit(1);
	}
	//创建空间存储
	int* tmp = (int*)malloc(sizeof(int) * k);
	if (tmp == NULL)
	{
		perror("TOP_K():Heap* tmp:error");
		exit(1);
	}
	//读取个数
	for (int i = 0; i < 10; i++)
	{
		fscanf(ps, "%d", &tmp[i]);
	}
	// 建堆,从最后一个非叶子节点开始建堆,
	// 这里的 -1-1 实际上看起来像是一个错误。
	// 通常,当我们需要找到最后一个非叶子节点的索引以开始建堆过程时,我们会从倒数第二个节点开始(因为数组索引从0开始)。对于大小为 k 的数组,最后一个非叶子节点的索引计算如下:
	// 简单的说就是,k是数值,我们需要传参传递是下标,找到父亲节点需要减去1 除以2 所以就有了-2的情况
	for (int i = (k - 1 - 1) / 2; i >= 0; i--)
	{
		AdjustDown(tmp, k, i);
	}
	//排序
	int val = 0;
	int ret = fscanf(ps, "%d", &val);
	while (ret != EOF)
	{
		if (tmp[0] < val)
		{
			tmp[0] = val;
			AdjustDown(tmp, k, 0);
		}
		ret = fscanf(ps, "%d", &val);
	}

	//打印
	for (int i = 0; i < k; i++)
	{
		printf("%d ", tmp[i]);
	}
	fclose(ps);

}

top_k完整代码

//TOP_K问题的实现 小堆寻找最大值
//创建随机数值
void TOP_K_fopen_w()
{
	FILE* ps = fopen("data.txt", "w");
	if (ps == NULL)
	{
		perror("FILE* ps :fopen:error");
		exit(1);
	}
	srand(time(0));
	for (int i = 0; i < 100000; i++)
	{
		int s = rand() % 10000;
		fprintf(ps, "%d\n", s);
	}

	fclose(ps);
}
//进行计算
void TOP_K()
{
	int k = 10;
	//scanf("%d", &k);
	FILE* ps = fopen("data.txt", "r");
	if (ps == NULL)
	{
		perror("Error:opening:file");
		exit(1);
	}
	//创建空间存储
	int* tmp = (int*)malloc(sizeof(int) * k);
	if (tmp == NULL)
	{
		perror("TOP_K():Heap* tmp:error");
		exit(1);
	}
	//读取个数
	for (int i = 0; i < 10; i++)
	{
		fscanf(ps, "%d", &tmp[i]);
	}
	// 建堆,从最后一个非叶子节点开始建堆,
	// 这里的 -1-1 实际上看起来像是一个错误。
	// 通常,当我们需要找到最后一个非叶子节点的索引以开始建堆过程时,我们会从倒数第二个节点开始(因为数组索引从0开始)。对于大小为 k 的数组,最后一个非叶子节点的索引计算如下:
	// 简单的说就是,k是数值,我们需要传参传递是下标,找到父亲节点需要减去1 除以2 所以就有了-2的情况
	for (int i = (k - 1 - 1) / 2; i >= 0; i--)
	{
		AdjustDown(tmp, k, i);
	}
	//排序
	int val = 0;
	int ret = fscanf(ps, "%d", &val);
	while (ret != EOF)
	{
		if (tmp[0] < val)
		{
			tmp[0] = val;
			AdjustDown(tmp, k, 0);
		}
		ret = fscanf(ps, "%d", &val);
	}

	//打印
	for (int i = 0; i < k; i++)
	{
		printf("%d ", tmp[i]);
	}
	fclose(ps);

}

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

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

相关文章

【物联网实战项目】STM32C8T6+esp8266/mqtt+dht11+onenet+uniapp

一、实物图 前端uniapp效果图&#xff08;实现与onenet同步更新数据&#xff09; 首先要确定接线图和接线顺序&#xff1a; 1、stm32c8t6开发板连接stlinkv2下载线 ST-LINK V2STM323.3V3.3VSWDIOSWIOSWCLKSWCLKGNDGND 2、ch340串口连接底座&#xff08;注意RXD和TXD的连接方式…

Spring Boot集成shiro之使用redis缓存demo

1.背景 上次发了这篇文章《Spring Boot集成Shiro快速入门Demo》后&#xff0c;有网友“just.blue”后台反馈集成redis有点问题&#xff0c;今天特地把集成过程发出来 2.为什么要使用cache 用来减轻数据库的访问压力&#xff0c;从而提升查询效率。 3.Shiro使用Redis做缓存 …

Go 实现 WebSocket 的双向通信

在Go语言中实现WebSocket的双向通信通常需要使用第三方库&#xff0c;其中 gorilla/websocket 是一个非常流行和广泛使用的库。 1、安装 go get github.com/gorilla/websocket 2、编写WebSocket服务器代码 package mainimport ("fmt""github.com/gorilla/we…

AlibabaCloud(阿里云)支付方式介绍,使用虚拟卡支付阿里云

一、支付方式 二、 添加支付方式 点击添加支付方式按钮&#xff0c;您将进入添加支付方式流程。选择您偏好的支付方式&#xff0c;按页面指导进行添加即可。 1、信用卡 可以使用Fomepay的信用进行支付&#xff0c;点击获取 依次输入您银行卡的卡号、有效期、安全码&#xff…

实现一个简单的 Google Chrome 扩展程序

目录 &#x1f9ed; 效果展示 # 图示效果 a. 拓展程序列表图示效果&#xff1a; b. 当前选项卡页面右键效果&#xff1a; c. 拓展程序消息提示效果&#xff1a; &#x1f4c7; 项目目录结构 # 说明 # 结构 # 文件一览 ✍ 核心代码 # manifest.json # background.j…

JWT-登录后下发令牌

后端 写一个jwt工具类&#xff0c;处理令牌的生成和校验&#xff0c;如&#xff1a; 响应数据样例&#xff1a; 前端要做的&#xff1a;

Nginx文件解析漏洞复现:CVE-2013-4547

漏洞原理 CVE-2013-4547漏洞是由于非法字符空格和截止符导致Nginx在解析URL时的有限状态机混乱&#xff0c;导致攻击者可以通过一个非编码空格绕过后缀名限制。假设服务器中存在文件1. jpg&#xff0c;则可以通过改包访问让服务器认为访问的为PHP文件。 漏洞复现 开启靶场 …

均值算法详细教程(个人总结版)

背景 均值算法&#xff0c;也称为平均值算法&#xff0c;是统计分析中的基本方法之一。它通过求取一组数据的平均值来概括数据的集中趋势。在数据分析、机器学习、信号处理等领域&#xff0c;均值算法被广泛应用。 均值的种类 算术均值&#xff08;Arithmetic Mean&#xff…

手把手教你快速玩转香橙派AIPro

什么是香橙AIPro&#xff1f; OrangePi AIpro(8T)采用昇腾AI技术路线&#xff0c;具体为4核64位处理器AI处理器&#xff0c;集成图形处理器&#xff0c;支持8TOPS AI算力&#xff0c;拥有8GB/16GB LPDDR4X&#xff0c;可以外接32GB/64GB/128GB/256GB eMMC模块&#xff0c;支持…

设计模式 19 模板模式 Template Pattern

设计模式 19 模板模式 Template Pattern 1.定义 模板模式&#xff08;Template Pattern&#xff09;是一种行为设计模式&#xff0c;它定义了一个算法的骨架&#xff0c;将一些步骤的具体实现延迟到子类中。在模板模式中&#xff0c;定义了一个抽象类&#xff0c;其中包含了一个…

2024.5组队学习——MetaGPT(0.8.1)智能体理论与实战(中):订阅智能体OSS实现

传送门&#xff1a; 《2024.5组队学习——MetaGPT&#xff08;0.8.1&#xff09;智能体理论与实战&#xff08;上&#xff09;&#xff1a;MetaGPT安装、单智能体开发》《2024.5组队学习——MetaGPT&#xff08;0.8.1&#xff09;智能体理论与实战&#xff08;下&#xff09;&…

2024年电工杯高校数学建模竞赛(A题) 建模解析| 园区微电网风光储协调优化配置

问题重述及方法概述 问题1&#xff1a;各园区独立运营储能配置方案及其经济性分析 经济性分析采用成本-效益分析方法&#xff0c;计算购电量、弃风弃光电量、总供电成本和单位电量平均供电成本等指标。 问题2&#xff1a;联合园区储能配置方案及其经济性分析 经济性分析采用成…

《Ai企业知识库》-rasa X安装使用

背景&#xff1a; Rasa X 是一个为构建、改进和管理对话式AI助手而设计的工具。它是Rasa开源机器学习框架的一个扩展&#xff0c;旨在实现“对话驱动开发”&#xff08;Conversation-Driven Development&#xff09;。Rasa X 主要特点包括&#xff1a; 交互式学习&#xff1a;…

百度智能小程序源码系统 关键词推广优化排名高 带完整的安装代码包以及搭建教程

系统概述 百度智能小程序源码系统是一套完整的解决方案&#xff0c;为用户提供了创建、发布和管理智能小程序的平台。它基于百度平台的先进技术&#xff0c;确保小程序在运行和展示方面具有出色的表现。 代码示例 系统特色功能 1.关键词推广优化&#xff1a;系统内置了强大的…

Day 40 Web容器-Tomcat

Tomcat 一&#xff1a;Tomcat简介 1.简介 ​ Tomcat是Apache软件基金会&#xff08;Apache Software Foundation&#xff09;的Jakarta 项目中的一个核心项目 ​ Tomcat服务器是一个免费的开放源代码的Web应用服务器&#xff0c;属于轻量级应用服务器 ​ Tomcat是WEB容器/WE…

JVM(内存区域划分、类加载机制、垃圾回收机制)

目录 一. 内存区域划分 1.本地方法栈(Native Method Stacks) 2.虚拟机栈(JVM Stacks) 3.程序计数器(Program Counter Register) 4.堆(Heap) 5.元数据区(Metaspace) 二.类加载机制 1.加载 2.验证 3.准备 4.解析 5.初始化 "双亲委派模型" 三. GC 垃圾回收…

[自动驾驶技术]-7 Tesla自动驾驶方案之算法(AI Day 2022)

特斯拉在2022年AI Day上更新了感知规控算法模型&#xff0c;核心引入了Occupancy技术。下图是特斯拉活动日展示的主题内容&#xff0c;本文主要解读Planning和Neural Network部分。 1 规划决策 Interaction search-交互搜索 特斯拉在自动驾驶规划中使用了一种高度复杂和优化的…

SpringCloud整合Seata1.5.2

Windows下部署Seata1.5.2可参照博文&#xff1a;Windows下部署Seata1.5.2&#xff0c;解决Seata无法启动问题-CSDN博客 1. 引入依赖 <!-- 分布式事务 --> <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-st…

echarts配置记录,一些已经废弃的写法

1、normal&#xff0c;4.0以后无需将样式写在normal中了 改前&#xff1a; 改后&#xff1a; DEPRECATED: normal hierarchy in labelLine has been removed since 4.0. All style properties are configured in labelLine directly now. 2、axisLabel中的文字样式无需使用te…

近五年营收和净利润大幅“败北”,尚品宅配今年押注扩张加盟

​ 《港湾商业观察》廖紫雯 两个月前经历过高管公开信的尚品宅配&#xff08;300616.SZ&#xff09;&#xff0c;无论是2023年年报&#xff0c;还是今年一季报&#xff0c;虽然公司净利润表现尚佳&#xff0c;但收入端的持续承压仍然备受关注。 今年一季报&#xff0c;尚品宅…