堆排序 之实现最小的K个数

news/2024/6/16 13:25:23

目录

1、方式一:通过自定义实现建堆和堆化操作

2、方式二:借助模块heapq实现

2.1、模块heapq的基本使用

2.2、使用heapq实现最小的k个数

3、堆在实际项目的应用

实现语言:Python 3.9

题目来源:牛客

分析:

  • 要找到最小的k个元素,只需要准备k个数字,之后每次遇到一个数字能够快速的与这k个数字中最大的值比较(大顶堆),每次将最大的值替换掉,那么最后剩余的就是k个最小的数字了。

为什么不是与k个元素中的最小值(小顶堆)进行比较呢?

  • 我们使用示例分析为什么使用小顶堆就不能实现,对于[4, 5, 1, 6, 2, 7, 3, 8] k = 4 建立小顶堆,建立的小顶堆为[1, 5, 4, 6] 堆顶元素为1,此时使用元素2和堆顶元素比较,比堆顶元素大,不加入堆顶;那么这样可见最后得到的结果一定不是最小的k个元素,所以不能使用小顶堆。

实现步骤:

  • 1:利用input数组中前k个元素,构建一个大小为k的大顶堆,堆顶为这k个元素的最大值。
  • 2:对于后续的元素,依次比较其与堆顶的大小,若是比堆顶小,则堆顶弹出,再将新数加入堆中,直至数组结束,保证堆中的k个最小。
  • 3:最后将堆顶依次弹出即是最小的k个数。

实现方式:

  • 方式一:通过自定义实现建堆和堆化操作
  • 方式二:借助Python模块heapq实现

1、方式一:通过自定义实现建堆和堆化操作

class Solution:def GetLeastNumbers_Solution(self , input: List[int], k: int) -> List[int]:# write code here# 建堆(从最后一个非叶子节点到根节点建堆)def buildHeap(a, n):i = n//2 - 1while i >=0:heapify(a, n, i)i = i - 1# 堆化(从上到下)def heapify(a, n, i):while True:maxPos = i# 和左子节点比较if i*2 + 1 <= n and a[i] < a[i*2+1]:maxPos = i*2 + 1# 和右子节点比较if i*2 + 2 <= n and a[maxPos] < a[i*2+2]:maxPos = i*2 + 2if maxPos == i:break# 交换节点a[i], a[maxPos] = a[maxPos], a[i]i = maxPos# 特殊情况处理if len(input) == 0 or len(input) <= k:return input# 先前k个数据建堆buildHeap(input, k)# 后面的节点依次和堆顶元素比较# 如果比堆顶元素小,将该元素加入堆顶,然后从堆顶开始堆化for i in range(k, len(input)):if input[0] > input[i]:# 该元素和堆顶元素交换input[0], input[i] = input[i], input[0]# 从堆顶元素开始从上往下堆化heapify(input, k, 0)return input[:k]

2、方式二:借助模块heapq实现

  • 注意:heapq模块默认建立的是小顶堆,所以需要借助这个特性自定义实现大顶堆

2.1、模块heapq的基本使用

import heapq# 创建一个空堆
heap = []# 往堆中添加元素
heapq.heappush(heap, 3)
heapq.heappush(heap, 1)
heapq.heappush(heap, 4)
heapq.heappush(heap, 1)
heapq.heappush(heap, 5)
# 弹出最小元素
print(heapq.heappop(heap))  # 输出 1
print(heapq.heappop(heap))  # 输出 1# 弹出最小元素并加入新元素
print(heapq.heapreplace(heap, 2))  # 输出 2# 将列表转化为堆
heap = [5, 8, 3, 0, 2]
heapq.heapify(heap)
print(heap)  # 输出 [0, 2, 3, 8, 5]# 获取最大的两个元素
print(heapq.nlargest(2, heap))  # 输出 [8, 5]
# 获取最小的两个元素
print(heapq.nsmallest(2, heap)) # 输出 [0, 2]

2.2、使用heapq实现最小的k个数

import heapq
class Solution:def GetLeastNumbers_Solution(self , input: List[int], k: int) -> List[int]:# 特殊情况处理if len(input) == 0 or len(input) < k or k == 0:return []# 自定义实现建立大顶堆def my_max_heapify(iterable):# 原理是对输入数据取反,这样建立的小顶堆,取数的时候进行取反即是大顶堆max_heap = [(-x, x) for x in iterable]# 建堆heapq.heapify(max_heap)# 返回max_heap中元祖数据的第二个,忽略第一个数据return [x for (_, x) in max_heap]# 前k个数据建堆max_heap = my_max_heapify(input[:k])# 后面的数据依次与堆顶元素比较for i in range(k, len(input)):if max_heap[0] > input[i]:# 弹出堆顶元素,加入新元素heapq.heapreplace(max_heap, input[i])# 再次对数据进行堆化max_heap = my_max_heapify(max_heap)return max_heap

3、堆在实际项目的应用

  1. 优先级队列:堆常常被用来实现优先级队列。在优先级队列中,元素被赋予一个优先级,并且总是按照优先级的顺序被处理。最大堆或最小堆可以根据需要用来实现具有最高或最低优先级元素始终位于队列头部的优先级队列。这种数据结构在任务调度、网络路由和事件处理等场景中非常有用。
  2. 堆排序:堆排序是一种基于堆的高效排序算法,其时间复杂度为O(nlogn)。它通过构建最大堆或最小堆,然后不断地取出堆顶元素(最大或最小值)并将其与堆的最后一个元素交换,然后重新调整堆的结构,直到整个数组有序。堆排序在处理大数据集时非常有效。
  3. 数据流中的Top K问题:在数据流处理中,经常需要找到数据流中最大的K个元素或最小的K个元素。这可以通过使用最大堆或最小堆来实现。具体做法是将数据流中的元素逐个插入堆中,并保持堆的大小为K。如果新插入的元素比堆顶元素(最大或最小)更大(或更小),则删除堆顶元素并插入新元素。这样,堆中始终保存着数据流中最大的K个元素或最小的K个元素。
  4. 合并有序文件:当需要合并多个有序文件为一个有序文件时,可以使用堆来实现。具体做法是将每个文件的第一个元素放入一个最小堆中,然后每次从堆中取出最小的元素并写入结果文件,然后从该元素所在的文件中取出下一个元素并重新放入堆中。重复这个过程直到所有文件都被处理完毕。
  5. 高性能定时器:在高性能定时器中,可以使用最小堆来管理定时任务。具体做法是将每个定时任务按照其触发时间放入最小堆中,然后每次从堆中取出触发时间最小的任务并执行。这样可以保证定时任务按照其触发时间的顺序被依次执行。
  6. 求解中位数:利用最大堆和最小堆,可以在O(logn)的时间内查询一组数据的中位数。具体做法是将数据分为两部分,一部分放入最大堆,另一部分放入最小堆,并保持最大堆中的元素个数不大于最小堆中的元素个数加1。这样,最大堆的堆顶元素(最大值)和最小堆的堆顶元素(最小值)的平均值就是当前数据的中位数。当插入新元素时,根据新元素与当前中位数的大小关系,将其放入最大堆或最小堆中,并重新调整两个堆的大小关系以保持平衡。

http://www.mrgr.cn/p/23011056

相关文章

示例七、超声波传感器测距

通过以下几个示例来具体展开学习,了解超声波传感器原理及特性&#xff0c;学习超声波传感器的应用&#xff1a; 示例七、超声波传感器测距 一、基本原理&#xff1a; 1、超声波测距仪的系统结构 利用超声测距原理测量物体之间的距离&#xff0c;当此距离小于某一设定值时&…

嵌入式软硬件设计流程

转载自:https://blog.csdn.net/jiangjunjie_2005/article/details/44024933从图书馆看到一经典国外嵌入式设计书籍,其中关于“软硬件设计流程”画得精彩,特列出如下:

ctfshow web入门 php反序列化 web267--web270

web267 查看源代码发现这三个页面 然后发现登录页面直接admin/admin登录成功 然后看到了 ///backdoor/shell unserialize(base64_decode($_GET[code]))EXP <?php namespace yii\rest{class IndexAction{public $checkAccess;public $id;public function __construct(){…

WPF 基础、WPF 相关知识、学习、参考项目

前言:最初参加工作时,做过WPF项目 ,后面几年后者虽然有写WPF项目,但多数都是边边角角,写一点满足工作需要。现在写下WPF,主要就是玩一玩,尝试下不同的东西。这是我的代码仓库:地址 (如果对您有帮助,给颗小星星奖励下吧),在WPF/Lesson 10 Practice/Practice/下面。基…

Rust Course学习(编写测试)

如果友友你的计算机上没有安装Rust&#xff0c;可以直接安装&#xff1a;Rust 程序设计语言 (rust-lang.org)https://www.rust-lang.org/zh-CN/ Introduce 介绍 Testing in Rust involves writing code specifically designed to verify that other code works as expected. It…

WPF 整体结构基础

前言:最初参加工作时,做过WPF项目 ,后面几年后者虽然有写WPF项目,但多数都是边边角角,写一点满足工作需要。现在写下WPF,主要就是玩一玩,尝试下不同的东西。这是我的代码仓库:地址 (如果对您有帮助,给颗小星星奖励下吧),在WPF/Lesson 10 Practice/Practice/下面。基…

使用Django中的Session和Cookie来传递数据

在Django中&#xff0c;Session和Cookie是两种常用的机制&#xff0c;用于在服务器端和客户端之间传递数据。下面我将简要介绍如何在Django中使用Session和Cookie来传递数据。 1、问题背景 在 Django 中&#xff0c;可以使用 request.POST 来获取表单提交的数据。但是&#xf…

最新ChatGPT中文系统网站源码+系统部署+支持AI对话、AI绘画、AI音乐等大模型

一、系统介绍 本文将介绍最新的ChatGPT中文版AI创作系统——星河易创AI系统&#xff0c;该系统基于ChatGPT的核心技术&#xff0c;融合了自然语言问答、绘画、音乐等创作功能&#xff0c;并兼容官方GPT全模型。该系统提供多样化的应用&#xff0c;包括GPTs的多场景应用、实时G…

布局全球内容生态,酷开科技Coolita AIOS以硬核品质亮相

当前&#xff0c;全球产业链供应链格局持续重构&#xff0c;成为影响中国对外经济发展的重要因素。2024年4月15至5月5日&#xff0c;历史久、规模大、层次高&#xff0c;作为中国外贸风向标的第135届中国进出口商品交易会&#xff08;即广交会&#xff09;在美丽的广州隆重举行…

CLI举例:通过URL分类控制用户访问的网站

华为CLI举例&#xff1a;通过URL分类控制用户访问的网站 配置基于URL分类的URL过滤功能&#xff0c;可以实现对用户访问的某一类网站的控制。既可以是FW自带的预定义分类&#xff0c;也可以是管理员配置的自定义分类。 组网需求 如图1所示&#xff0c;FW作为企业网关部署在网络…

Spring如何解决循环依赖问题?

当然是用三级缓存来解决循环依赖问题。 那二级缓存能解决吗&#xff1f; 首先我们要知道Spring bean的生命周期 1.实例化&#xff08;new&#xff09; 2.属性赋值&#xff08;populate&#xff09; 3.初始化 一堆钩子函数&#xff08;动态代理的生成也在这一步&#xff09…

【机器学习】卷积神经(CNN)在图像识别中的革命性应用:自动驾驶的崛起

卷积神经网络&#xff08;CNN&#xff09;在图像识别中的革命性应用&#xff1a;自动驾驶的崛起 一、卷积神经网络&#xff08;CNN&#xff09;的基本原理二、CNN在图像识别中的显著成果三、CNN在自动驾驶汽车中的物体检测和识别四、CNN在图像识别中的代码实例 随着人工智能和深…

一、RocketMQ基本概述与部署

RocketMQ基本概述与安装 一、概述1.MQ概述1.1 用途1.2 常见MQ产品1.3 MQ常用的协议 2.RocketMQ概述2.1 发展历程 二、相关概念1.基本概念1.1 消息&#xff08;Message&#xff09;1.2 主题&#xff08;Topic&#xff09;1.3 标签&#xff08;Tag&#xff09;1.4 队列&#xff0…

鸿蒙内核源码分析(文件句柄篇) | 你为什么叫句柄

句柄 | handle int open(const char* pathname,int flags); ssize_t read(int fd, void *buf, size_t count); ssize_t write(int fd, const void *buf, size_t count); int close(int fd);只要写过应用程序代码操作过文件不会陌生这几个函数,文件操作的几个关键步骤嘛,跟把大…

智能工作流:Spring AI高效批量化提示访问方案

集用SpringAI搭建系统,依靠线程池\负载均衡等技术进行请求优化,用于解决科研&开发过程中对GPT接口进行批量化接口请求中出现的问题。大语言模型接口以OpenAI的GPT 3.5为例,JDK版本为17。基于SpringAI搭建系统,依靠线程池\负载均衡等技术进行请求优化,用于解决科研&…

【小白可懂】SpringBootWeb入门

web开发需要的技术栈&#xff1a; 前端web开发&#xff1a; html css javascript Vue Element Nginx 后端web开发&#xff1a; Maven SpringBoot Web 基础篇 MySOL SpringBoot Mybatis SpringBoot Web开发篇 SpringBoot web进阶篇 什么是spring&#xff1f; 官网&a…

修改el-checkbox样式

一定要在最外层&#xff1b; //未选中框/deep/ .el-checkbox__inner{border-color: #0862a3;}//选中框/deep/ .el-checkbox__input.is-checked .el-checkbox__inner{background-color: #0862a3;border-color: #0862a3;}//未选中框时右侧文字/deep/ .el-checkbox__label{}//选中…

NLP 词嵌入向量即word embedding原理详解

文章目录 1. 前言2. 目标3. CBOW4. 训练结果5. 如何使用6. 延伸7. 参考 1. 前言 现在 NLP 相关的技术大概率会接触到词向量、word embedding&#xff08;词嵌入&#xff09;诸如此类的术语。然后网上一搜&#xff0c;哦&#xff0c;有一个 Word2Vec 的技术&#xff0c;能够把单…

测斜仪的具体应用:从地下工程到斜坡监测

测斜仪作为一种精密的测量工具&#xff0c;在多个领域都有广泛的应用。从最初的地下工程&#xff0c;到现今的斜坡监测&#xff0c;测斜仪的技术进步和应用范围的扩大&#xff0c;为工程安全提供了有力的保障。 一、地下工程中的测斜仪应用 在地下工程中&#xff0c;测斜仪主要…

微信登录功能--网站应用

微信开发平台注册https://open.weixin.qq.com/ 账号中心-填写基本资料&#xff08;最好是公司注册&#xff09; 账号中心-开发者资质认证&#xff08;充钱&#xff0c;300&#xff09; 审核通过之后&#xff0c;管理中心-网站应用-创建网站应用&#xff08;AppSecret一定一定…