【Python Cookbook】S01E03 找到最大最小的N个元素

news2024/10/4 18:21:16

目录

  • 问题
  • 解决方案
  • 讨论

问题

如何在一个集合中找到最大或最小的 N 个元素?

解决方案

使用 heapq 模块。

pip install heapq

heapq 模块中,有 nlargest() 以及 nsmallest() 两个函数:

import heapq

nums = [1, 8, 23, 2, 7, -4, 8, 18, 42, 37]
print(heapq.nlargest(3, nums))
print(heapq.nsmallest(3, nums))

在这里插入图片描述

# nlargest函数结构
nlargest(n, arr, key)		# 其中n为取出的数量,arr为数组
# nsmallest函数结构
nsmallest(n, arr, key)

而由于这两个函数 nlargest() nsmallest 都接受一个参数 key,有了这个参数,就可以允许它们工作在更加复杂的数据结构之中。

import heapq

profolio = [
    {"name":"IBM", "shares": 100, "price": 91.1},
    {"name":"AAPL", "shares": 50, "price": 543.22},
    {"name":"FB", "shares": 200, "price": 21.09},
    {"name":"HPQ", "shares": 35, "price": 31.75},
    {"name":"ACME", "shares": 75, "price": 115.65}
]

cheap = heapq.nsmallest(3, profolio, key=lambda s:s['price'])
print(cheap)

在这里插入图片描述

讨论

如果寻找集合 A A A 中最大最小的 N N N 个元素,且 N < < l e n ( A ) N<<len(A) N<<len(A),那么使用下述方案可以提供更好的性能。

首先函数会在底层将集合转化为列表,元素会以堆的顺序排列。

import heapq

nums = [1, 8, 2, 23, 7, -4, 18, 23, 42, 37, 2]
heap = list(nums)
heapq.heapify(heap)
print(heap)

上述代码 print(heap) 的结果为:

[-4, 2, 1, 23, 7, 2, 18, 23, 42, 37, 8]

在堆数据结构中,父节点和子节点的关系是基于数组的索引来确定的。对于一个给定的节点,其索引为 i i i,它的父节点、左子节点和右子节点的索引可以通过特定的公式计算得出。

而在 Pythonheapq 模块实现的最小堆中,堆是一个列表,且堆属性满足对于所有索引 i i i(除了根节点,其索引为0),都有 h e a p [ i ] > = h e a p [ ( i − 1 ) / / 2 ] heap[i] >= heap[(i-1)//2] heap[i]>=heap[(i1)//2]

即任何父节点的值都小于或等于其子节点的值。

[-4, 2, 1, 23, 7, 2, 18, 23, 42, 37, 8]

在这个堆中,

  • 索引 0 的元素是 -4,它是根节点,没有父节点。
  • 索引 1 的元素是 2,它的父节点是 -4(索引为 (1-1)//2 = 0)。
  • 索引 2 的元素是 1,它的父节点也是 -4(索引为 (2-1)//2 = 0)。
  • 索引 3 的元素是 23,它的父节点是 2(索引为 (3-1)//2 = 1)。
  • 索引 4 的元素是 7,它的父节点是 2(索引为 (4-1)//2 = 1)。
  • 索引 5 的元素是 2,它的父节点是 1(索引为 (5-1)//2 = 2)。
  • 以此类推,可以找到每个节点的父节点。

同样地,可以找到每个节点的子节点:

  • 索引 0 的 -4 的左子节点是 2(索引为 2*0 + 1 = 1),右子节点是 1(索引为 2*0 + 2 = 2)。
  • 索引 1 的 2 的左子节点是 23(索引为 2*1 + 1 = 3),右子节点是 7(索引为 2*1 + 2 = 4)。
  • 索引 2 的 1 的左子节点是 2(索引为 2*2 + 1 = 5),但没有右子节点(因为索引 2*2 + 2 = 6 处没有元素)。
  • 以此类推,可以找到每个节点的子节点。

Pythonheapq 模块提供了一个 heapify 函数,该函数能够将一个可变的列表转换为最小堆。过程是自动的,但是可以进行模拟:

  1. 首先找到最后一个非叶子节点的索引:
    • 在一个完全二叉树中,最后一个非叶子节点的索引是 len(heap) // 2 - 1
    • 而本列表中, len(nums) = 11,所以最后一个非叶子节点的索引是 11 // 2 - 1 = 4
  2. 从最后一个非叶子节点开始,向上进行堆化(heapify):
    • 对于每个节点,比较它与它的子节点的值。
    • 如果节点的值大于其子节点中的最小值,则交换这个节点与其最小子节点的值。
    • 重复这个过程,直到堆的根节点。
  3. 重复步骤2,直到整个列表满足堆属性。

手动模拟过程:

# 初始列表
heap = [1, 8, 2, 23, 7, -4, 18, 23, 42, 37, 2]

# 从最后一个非叶子节点开始,向上进行堆化
last_non_leaf = len(heap) // 2 - 1
for i in range(last_non_leaf, -1, -1):
    # 比较当前节点与其子节点的值,并进行交换
    current = heap[i]
    left_child_idx = 2 * i + 1
    right_child_idx = 2 * i + 2
    smallest = i

    # 如果左子节点存在且小于当前节点,更新最小值索引
    if left_child_idx < len(heap) and heap[left_child_idx] < current:
        smallest = left_child_idx

    # 如果右子节点存在且小于最小值,更新最小值索引
    if right_child_idx < len(heap) and heap[right_child_idx] < heap[smallest]:
        smallest = right_child_idx

    # 如果当前节点不是最小值,交换它们
    if smallest != i:
        heap[i], heap[smallest] = heap[smallest], heap[i]

# 最终的堆
print(heap)

执行上述代码后,我们得到了一个最小堆。这个过程是迭代的,从最后一个非叶子节点开始,向上逐步将每个节点与其子节点进行比较和交换,直到整个列表满足堆属性。

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

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

相关文章

Matlab中% note that Wilkinson notation (‘L1~L4~1‘) is used to specify the model

fitrm 函数的输入参数不正确&#xff0c;似乎出错的地方是在定义 fitrm 对象时使用了不正确的参数。 fitrm 函数的语法是这样的&#xff1a; rm fitrm(tbl, model, WithinDesign, withinDesign) 其中&#xff1a; - tbl 是一个表格&#xff0c;包含了待分析的数据。 - mod…

WPF使用Prism实现简单订餐系统

新建wpf项目&#xff0c;nuget引入Prism.DryIoc&#xff0c;MaterialDesignThemes 引入后&#xff0c;修改App.xaml 前台引入 xmlns:prism"http://prismlibrary.com/"和prism:PrismApplication App.xaml.cs App.xaml.cs继承PrismApplication&#xff0c;重写CreateS…

这款AI绘画软件,带你快速生成高质量产品效果图!

前言 随着人工智能技术的飞速发展&#xff0c;AI在设计领域的应用越来越广泛&#xff0c;。今天&#xff0c;介绍的一款能够自动生成高质量产品效果图的AI绘画软件——STARTAI。这款软件以其强大的功能和便捷的操作&#xff0c;正在重新定义电商产品效果图的制作流程。 AI局部…

nginx学习记录-防盗链

1. 防盗链的概念 防盗链&#xff0c;顾名思义就是防止盗取链接&#xff0c;这里的链接一般是资源链接。 如图所示&#xff0c;我们访问一个网站时&#xff08;比如百度&#xff09;&#xff0c;我们第一个请求会获得一个html页面&#xff0c;页面中包含各种资源链接&#xff0…

LeetCode题练习与总结:平衡二叉树--110

一、题目描述 给定一个二叉树&#xff0c;判断它是否是平衡二叉树。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;true示例 2&#xff1a; 输入&#xff1a;root [1,2,2,3,3,null,null,4,4] 输出&#xff1a;false示例 3&#xff1a…

第十三章 进程与线程

第十三章 进程与线程 程序与进程的概念 程序&#xff1a; 英文单词为Program&#xff0c;是指一系列有序指令的集合&#xff0c;使用编程语言所编写&#xff0c;用于实现一定的功能。 进程&#xff1a; 进程则是指启动后的程序&#xff0c;系统会为进程分配内存空间。 函数式…

汇编小习题

汇编你还想及格&#xff1f; 未完待续 1. 注释下面代码 Title Hello Word .386 ;使用80386指令集 .model flat, stdcall;内存模型为平坦模型&#xff0c;子程序采用stdcall约定 .stack 4096;为运行时堆栈分配4096空间 ExitProcess proto , dwExitCode:DWORD;为过程创建过程原…

超好用的加密工具

超好用的加密工具 背景 介于行业原因经常要对相关文件进行加密传输&#xff0c;尽可能避免文件的泄漏&#xff0c;保护群众的隐私。于是我就开发了一个非常好用的加密工具。 环境 本工具目前只适用 Windows 操作系统,最好是Windows8以上&#xff0c;否则需要下载额外的依赖…

门限签名技术

私钥永远不存在 (t, n) 门限签名方案 (TSS) 是一种密码协议&#xff0c;允许一组 n 个参与者共同签署文档或交易&#xff0c;其中 t 1 个或更多参与者的任何子集都可以产生有效签名&#xff0c;但 t 的子集 或更少的人不能。 该方案旨在通过确保没有任何一方可以单方面生成签名…

Paddle使用问题No module named ‘paddle.fluid’

这是Paddle版本的问题&#xff0c;从飞桨框架 2.5 版本开始&#xff0c;已经废弃了 paddle.fluid 。 ​解决方案&#xff1a;修改paddle版本 pip install paddlepaddle2.4.0

Prompt工程与实践

Prompt工程与实践 一、Prompt与大模型 1.1 大模型的定义 大模型本质上就是一个概率生成模型&#xff0c;该模型的模型参数足够大&#xff0c;并且在训练过程中阅读了非常多的各个领域的语料。这个时候&#xff0c;如果通过一个正确的、有效的指令去引导这个模型&#xff0c;…

算法-从归并排序到归并分治

文章目录 前言介绍1 . 简单的归并排序2 . 数组的最小和问题3 . 逆序数对问题4 . 翻转对数量的计算 前言介绍 归并排序是Merge sort&#xff09;是一种有效、稳定的排序算法&#xff0c;它采用了分治法&#xff08;Divide and Conquer&#xff09;的典型应用,何为分治 ? 即把多…

【Linux】Linux基本指令2

我们接着上一篇&#xff1a;http://t.csdnimg.cn/bSJx8 我们接着完善ls指令 我们可以直接匹配对应格式的文件匹配出来 1.man指令&#xff08;重要&#xff09;&#xff1a; Linux的命令有很多参数&#xff0c;我们不可能全记住&#xff0c;我们可以通过查看联机手册获取帮助…

【贪心算法】C++解决回文串、增减字符串匹配、分发饼干、跳跃游戏、加油站问题

1. 前言 贪心算法&#xff08;Greedy Algorithm&#xff09;是一种在每一步选择中都采取当前状态下最优决策的算法。贪心算法通常用来解决最优化问题&#xff0c;其核心思想是通过局部最优解逐步推导出全局最优解。 在贪心算法中&#xff0c;我们并不总是考虑到未来可能发生的…

【PingPong_注册安全分析报告】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞 …

如何下载b站(哔哩哔哩bilibili)的学习视频教程

方法1&#xff1a; 打开粘贴视频链接下载即可哔哩哔哩(bilibili)视频解析下载 - 保存B站视频到手机、电脑哔哩哔哩高清视频解析下载工具是一个免费的B站视频在线解析提取工具,支持提取B站APP和bilibili网站上的任何视频,提取出来的视频无水印.我们可以借助此下载器方便地将视频…

使用jdk自带jhat工具排查OOM问题

使用jdk自带jhat工具排查OOM问题 OOM java.lang.OutOfMemoryError: Java heap space排查步骤 编写一个测试类 public class TestJVM {Testpublic void test1() throws InstantiationException, IllegalAccessException {List<A> list new ArrayList<>();for (i…

ArcGIS不同图斑设置不同的透明度

对于设置一个图层的整体的透明度&#xff0c;我们在 ArcGIS制作带蒙版的遥感影像地图http://mp.weixin.qq.com/s?__bizMzIzNjM2NTYxMg&mid2247509080&idx1&sn38dccf0a52bb3bb3758f57114ee38b72&chksme8da161bdfad9f0d363da90959a8524dcf2b60d0e8d999f8ebeef0…

OrangePi Alpro开箱体验 ubuntu 与 openEuler 实时性对比

OrangePi Alpro开箱体验 & ubuntu 与 openEuler 实时性对比 1 介绍1.1 概述1.2 OrangePi Kunpeng Pro vs OrangePi AIpro 2 开箱3 芯片介绍OrangePi AIpro(8T)Atlas 200I DK A2 4 开机连接鼠标、键盘、显示器桌面查看系统信息配置网络查看IP远程SSHWinSCP 5 GPIO Toolgpio_…

MATLAB分类与判别模型算法:基于LVQ神经网络的乳腺肿瘤诊断分类程序【含Matlab源码 MX_003期】

说明 实现基于LVQ&#xff08;Learning Vector Quantization&#xff0c;学习向量量化&#xff09;神经网络的乳腺肿瘤诊断分类任务。LVQ是一种监督学习算法&#xff0c;通常用于模式识别和分类任务。 算法思路介绍&#xff1a; 导入数据&#xff1a; 加载名为"data.mat&…