Leetcode 剑指 Offer II 159. 库存管理 III

题目难度: 简单

原题链接

今天继续更新 Leetcode 的剑指 Offer(专项突击版)系列, 大家在公众号算法精选里回复剑指offer2就能看到该系列当前连载的所有文章了, 记得关注哦~

题目描述

仓库管理员以数组 stock 形式记录商品库存表,其中 stock[i] 表示对应商品库存余量。请返回库存余量最少的 cnt 个商品余量,返回 顺序不限。

示例 1:

  • 输入:stock = [2,5,7,4], cnt = 1
  • 输出:[2]

示例 2:

  • 输入:stock = [0,2,3,6], cnt = 2
  • 输出:[0,2] 或 [2,0]

提示:

  • 0 <= cnt <= stock.length <= 10000
  • 0 <= stock[i] <= 10000

题目思考

  1. 最简单的方案是什么?
  2. 如何一步步优化?

解决方案

方案 1

思路
  • 一个最简单的思路相信大家都很容易想到, 那就是排序然后取前 cnt 个, 一行代码完事…
  • 但这种方案时间复杂度比较差, 特别是当 N 特别大的时候, 所以还是有很多可以优化的地方
复杂度
  • 时间复杂度O(NlogN)
    • 需要排序
  • 空间复杂度O(1)
    • 不需要额外空间(原地排序时)
代码
classSolution:definventoryManagement(self,stock:List[int],cnt:int)->List[int]:returnsorted(stock)[:cnt]

方案 2

思路
  • 维护一个大小为 cnt 的最大堆, 然后从头开始遍历:
    • 当堆中元素数目不足 cnt 的时候, 直接加入堆中
    • 否则要判断当前元素与堆顶大小, 如果当前元素更小的话, 就要拿它替代堆顶元素
  • 这样最终堆中的元素就是最小的 cnt 个元素,因为更大的元素在之前的遍历中就被替换出去了, 或者根本不会被加入堆中
  • 这里先使用语言自带的优先队列来实现, 相比自己实现的版本会有所优化, 且代码更为精简
  • python 对应的就是 heapq, 不过需要注意 heapq 是最小堆, 所以我们需要取相反数人为将其变成最大堆…
  • 下面代码有详细的注释, 方便大家理解
复杂度
  • 时间复杂度O(NlogK)
    • 只需要遍历数组一遍, 遍历的时候需要插入堆, 插入的时间复杂度为O(logK)
  • 空间复杂度O(K)
    • 堆空间的消耗
代码
importheapqclassSolution:definventoryManagement(self,stock:List[int],cnt:int)->List[int]:# 注意k为0的特殊情况, 返回空数组ifcnt==0:return[]maxheap=[]forainstock:# 关键判断条件: 堆元素数目小于cnt/当前元素小于堆顶iflen(maxheap)<cntor-maxheap[0]>a:# 注意取相反数转成最大堆heapq.heappush(maxheap,-a)# 如果堆元素超过cnt的话, 弹出堆顶iflen(maxheap)>cnt:heapq.heappop(maxheap)# 注意转回原来的数return[-xforxinmaxheap]

方案 3

思路
  • 和方案 2 一样, 但是面试官可能会要求你自己实现一个最大堆, 那就自己实现吧…
  • 可以使用一个数组来模拟堆, 然后根据下标关系模拟堆的上浮和下沉操作
  • 注意这里有所简化, 因为不需要每次追加元素, 而是说每次用新元素替换堆顶, 所以只需要下沉操作即可
  • 下面代码有详细的注释, 方便大家理解
复杂度
  • 时间复杂度O(NlogK)
    • 只需要遍历数组一遍, 遍历的时候需要插入堆, 插入的时间复杂度为O(logK)
  • 空间复杂度O(K)
    • 堆空间的消耗
代码
classMaxHeap:def__init__(self,stock):self.heap=stockforiinrange(len(stock)//2+1)[::-1]:# 这里使用快速建堆法构造出大小为cnt的堆, 即从n/2到0依次做下沉操作# 也可以用插入法建堆, 那样可以初始化堆为空, 但需要额外实现上浮操作self.sink(i)defadd(self,v):ifv<self.heap[0]:# 只有当前元素小于堆顶时才替换并下沉self.heap[0]=v self.sink(0)defsink(self,i):# 下标从0开始, 所以左子节点下标是2i+1child=2*i+1whilechild<len(self.heap):ifchild+1<len(self.heap)andself.heap[child+1]>self.heap[child]:# 右子节点存在且更大, 使用它child+=1ifself.heap[child]>self.heap[i]:# 只有当子节点比当前节点大的时候才交换self.heap[i],self.heap[child]=self.heap[child],self.heap[i]i=child child=2*i+1else:# 否则说明不需要继续下沉了, 直接退出breakclassSolution:definventoryManagement(self,stock:List[int],cnt:int)->List[int]:ifcnt==0:return[]# 初始化为前cnt个元素, 一次性下沉建堆maxheap=MaxHeap(stock[:cnt])forainstock[cnt:]:# 此时堆中已有cnt个元素, 只需要比较堆顶和当前元素即可, 将相关逻辑封装在add方法中maxheap.add(a)returnmaxheap.heap

方案 4

思路
  • 回忆快速排序, 它的做法是根据 pivot 将数组分成两部分, 很契合这里的要求
  • 所以我们可以直接利用它的思路, 不同的是划分之后这里只需要往一边递归, 类似二分查找的过程, 而不需要两边都排序
  • 举个例子, 比如 n 是 10, cnt 是 3, 第一次划分之后的下标为 5, 那么我们只需要再考虑[0,4]的部分即可
  • 下面代码有详细的注释, 方便大家理解
复杂度
  • 时间复杂度平均O(N), 最差O(N^2)
    • 如果每次划分都平分的话, 就是N+N/2+N/4+...的等比序列, 总和为 2N, 所以是O(N)
    • 而最差情况是每次都只划分走了一个元素, 这样就是N+(N-1)+(N-2)+..., 就是O(N^2)
  • 空间复杂度O(logN)
    • 递归的栈的平均深度
代码
classSolution:definventoryManagement(self,stock:List[int],cnt:int)->List[int]:ifcnt==0:return[]defpartition(s,e):ifs>=e:# 递归出口, 此时不需要额外划分returnpivot=stock[s]i,j=s,e# 经典快速排序过程, 只是不需要像排序那样找到划分点后同时递归左右两个区间whilei<j:# 先从后向前找第一个<pivot的数, 并放在上一个空出来的坑中(最开始空出来的坑就是左边界s, 它的值已经被存储下来了, 所以必须先从后向前找)whilei<jandstock[j]>=pivot:j-=1stock[i]=stock[j]# 再从前向后找第一个>pivot的数, 并放在上一个空出来的坑中(下标j, 因为它已经被放入上一个下标为i的坑中了)whilei<jandstock[i]<=pivot:i+=1stock[j]=stock[i]stock[i]=pivotifi==cnt-1:# 当前划分点恰好划分出前cnt个最小数(包含i元素本身), 直接返回即可# 当然这里用cnt来判断也行, 那下面的判断条件也要把cnt-1改成cnt, 就是说i左边的肯定是最小的cnt个returnelifi<cnt-1:# 当前划分点不能划分出前cnt个最小数, 需要往右继续找partition(i+1,e)else:# 当前划分点划分了多于cnt个最小数, 需要往左继续找partition(s,i-1)partition(0,len(stock)-1)returnstock[:cnt]

大家可以在下面这些地方找到我~😊

我的 GitHub

我的 Leetcode

我的 CSDN

我的知乎专栏

我的头条号

我的牛客网博客

我的公众号: 算法精选, 欢迎大家扫码关注~😊

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

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

相关文章

把3D人物模型导入Unity,并给头发衣服附加重力

【【如何将原神的角色导入Unity】全网最细致教程,全程干货。不使用任何收费插件,使用Spring Bone对头发和衣服进行物理模拟。】https://www.bilibili.com/video/BV1G34y127e6?vd_source=256a31ec907fa4985a200f42dc…

Spring AOP和AspectJ的区别

一、实现原理的本质区别 Spring AOP是基于动态代理实现的。在运行时,Spring会为目标Bean创建一个代理对象。如果目标类实现了接口,就用JDK动态代理;如果没有接口,就用CGLIB生成子类代理。所有方法调用都先经过代理…

盒马鲜生礼品卡回收平台实测,京顺回收成行业优选

在闲置盒马鲜生礼品卡回收领域,安全高效地选择回收平台是消费者的关注重点。本文基于实测体验与行业数据,深度剖析京顺回收在盒马鲜生礼品卡回收场景中的核心优势。 一、实测背景:资质流程双优 小张手握3张面值500元…

外包干了9天,技巧退步明显。。。。。

外包干了9天,技巧退步明显。。。。。2026-01-25 19:51 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !i…

我们和钱的关系,其实早被财富量级定好了

我们和钱的关系,其实早被财富量级定好了 目录 我们和钱的关系,其实早被财富量级定好了 一个人有了一百万或几百万,你会感到你是金钱的爸爸。有了一千万或几千万,你会感到你是金钱的爷爷。做金钱的爷爷,是人和金钱之间最优越最良好的关系……一旦超过了几千万,人和金钱的平…

人生的本质是交换:成事的终极公式:极致专注+灵活交换=一切皆可行

人生的本质是交换:深耕一技+巧做链接,才是普通人的破局之道 目录 人生的本质是交换:深耕一技+巧做链接,才是普通人的破局之道 把“交换”这件事做透 自己有“可交换的资本” 交换的底层前提:你得真的“行”,更要让别人“认” 交换的核心逻辑:靠一技之长求温饱,靠价值交…

31岁仍被说幼稚:上班最狠的PUA是让我们盼着自己变老

31岁仍被说幼稚:上班最狠的PUA是让我们盼着自己变老 目录 31岁仍被说幼稚:上班最狠的PUA是让我们盼着自己变老 一、上班的隐形陷阱:为了“不用上班”,我们主动期待衰老 “快点变老吧,老了就不用上班了。” 二、赚钱的底层逻辑:别把“工具”当成“目的” 钱是为了服务于人…

AI也会“断片”?换个提问顺序,大模型直接变“差生”

🤖 AI也会“断片”?换个提问顺序,大模型直接变“差生” 目录 🤖 AI也会“断片”?换个提问顺序,大模型直接变“差生” 🧪 用一道选择题,看穿大模型的“注意力陷阱” ✅ 【正常顺序:CQO】 ❌ 【“坑人”顺序:QOC】 🧠 为什么换个顺序就“翻车”?因果注意力的天生…

AI版“马后炮”?大模型的「因果注意力」到底是啥?

AI版“马后炮”?大模型的「因果注意力」到底是啥? 目录 AI版“马后炮”?大模型的「因果注意力」到底是啥? 这一切的根源,都指向大模型天生自带的**「因果注意力」机制**。 🔍 什么是「因果注意力」?用“写日记”打比方 📝 生活化举例 🧠 底层原理:Transformer里的…

真正决定你成长速度的,从来不是你“经历了什么”,而是你“反思透了什么”

真正决定你成长速度的,从来不是你“经历了什么”,而是你“反思透了什么” 第一原则:前提你是充足的尝试,现在这个社会有可能你连经历的机会都没有,一个机会都得费劲的争取才行; 第二原则:反思是我们爱好的事情,让你感到不舒服的事情想都是浪费自己时间,例如职场扯皮…

你看到的人不舒服,就是不好,远离就行,或者不说话不表态:你是世界和核心,没有你,世界将不在存在

“驭人术”清单,把职场的脏底裤都扒下来了 目录 “驭人术”清单,把职场的脏底裤都扒下来了 你看到的人不舒服,就是不好,远离就行,或者不说话不表态 你是世界和核心,没有你,世界将不在存在 这些“驭人术”,本质是职场PUA的变种 真正的带人,从来不是“驭人” 打工人该怎…

学长亲荐!专科生毕业论文必备!8款一键生成论文工具TOP8测评

学长亲荐&#xff01;专科生毕业论文必备&#xff01;8款一键生成论文工具TOP8测评 2026年专科生毕业论文工具测评&#xff1a;从功能到体验的深度解析 随着人工智能技术的不断进步&#xff0c;越来越多的专科生开始借助AI工具辅助完成毕业论文写作。然而&#xff0c;面对市场上…

别再乱用 `enum` 了!聊聊 C++ 类里枚举的“坑”与“真香”定律

写了这么多年 C&#xff0c;我发现一个很有意思的现象&#xff1a;很多新手&#xff08;甚至一些老鸟&#xff09;在类里定义状态或者类型时&#xff0c;还是习惯性地敲下 enum。倒不是说不能用&#xff0c;而是在 C11 甚至 C20 的今天&#xff0c;无脑用 enum 往往是在给未来的…

过年和父母吵到沉默才懂:我花了20年,终于“背叛”了他们的人生; 家族第一个博士:撕开阶层的口子,带家人杀出重围

过年和父母吵到沉默才懂:我花了20年,终于“背叛”了他们的人生 目录 过年和父母吵到沉默才懂:我花了20年,终于“背叛”了他们的人生 不是“稳定最重要”,而是“喜欢才最重要” 不是“别人都这样”,而是“我想这样” 不是“活成别人期待的样子”,而是“活成真正的自己” …

基于51单片机wifi烟雾温湿度检测 无线物联网 火灾报警系统diy

目录系统概述核心硬件组成软件设计要点系统搭建步骤扩展功能建议注意事项源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;系统概述 基于51单片机的WiFi烟雾温湿度检测系统是一种低成本、高实用性的火灾报警DIY方案。该系统通过传感器实…

STM32单片机车载酒精检测 防酒驾系统 酒精报警器套件GSM

目录 STM32单片机车载酒精检测系统概述核心功能模块硬件组成清单软件设计要点典型工作流程应用场景扩展注意事项 源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01; STM32单片机车载酒精检测系统概述 该系统基于STM32单片机设计&#xff…

基于32单片机气体监测系统PM2..5烟雾甲醛 温湿度WIFI传输APP显示

目录 系统概述硬件组成软件设计关键实现步骤扩展功能注意事项 源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01; 系统概述 基于32位单片机&#xff08;如STM32&#xff09;的气体监测系统可实时检测PM2.5、烟雾、甲醛及温湿度数据&#…

基于51单片机 智能鞋柜 语音识别 杀菌消毒无线控制DIY成品

目录 基于51单片机的智能鞋柜DIY方案硬件组成清单关键电路设计软件逻辑框架成品优化建议扩展功能实现 源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01; 基于51单片机的智能鞋柜DIY方案 核心功能 语音识别控制&#xff1a;通过LD3320等…

基于51单片机CO2浓度 温室大棚 二氧化碳检测

目录51单片机在CO2浓度检测中的应用系统组成模块硬件连接示例关键代码片段数据处理与校准扩展功能建议源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;51单片机在CO2浓度检测中的应用 51单片机因其成本低、稳定性高、易于编程等特点&am…

基于51单片机GPS的公交车自动报站系统GPS自动报站器检测系统DIY

目录 系统概述硬件组成工作原理关键算法代码片段&#xff08;C51示例&#xff09;调试要点扩展功能 源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01; 系统概述 基于51单片机的GPS公交车自动报站系统是一种低成本、高精度的解决方案&…