首页 文章 精选 留言 我的

精选列表

搜索[国密算法],共10000篇文章
优秀的个人博客,低调大师

算法图解:如何找出栈中的最小值?

作者 | 王磊 来源 | Java中文社群(ID:javacn666) 转载请联系授权(微信ID:GG_Stone) 前面我们学习了很多关于栈的知识,比如《动图演示:手撸堆栈的两种实现方法!》和《JDK 竟然是这样实现栈的?》,那么接下来我们再来刷一些关于栈的经典面试题以巩固学过的知识。 我们今天的面试题是这样的... 题目 定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。 示例: MinStack minStack = new MinStack(); minStack.push(-2); minStack.push(0); minStack.push(-3); minStack.min(); --> 返回 -3. minStack.pop(); minStack.top(); --> 返回 0. minStack.min(); --> 返回 -2. LeetCode 地址:https://leetcode-cn.com/problems/bao-han-minhan-shu-de-zhan-lcof/ 思考 首先来说这道题目本身很好理解,它的实现难点在于以下两个方面: 当我们进行 pop(移除栈顶元素)操作时如果删除的是当前最小值,那么我们如何寻找下一个最小值? 要保证调用 min、push 及 pop 的时间复杂度都是 O(1)。 也就是说,在我们执行了 pop 时如果移除的栈中最小的值,那么如何寻找栈中的下一个最小元素?并且要保证操作的时间复杂度为 O(1)。这个时间复杂度制约了我们在移除了最小值之后不能通过遍历查找下一个最小值,所以这就成为了这道题的难点。 比如当我们移除以下栈顶元素值: 因为最小值就是 1,因此在移除之后最小值也被移除了,如下图所示: 那么接下来,让我们一起思考 3 分钟,想一想应该如何处理这个问题~ 解题思路 其实我们可以在每次入栈时,判断当前元素是否小于最小值,如果小于则将原最小值和最新的最小值相继入栈,这样在调用 pop 时即使移除的是最小值,我们也能通过获取下一个元素得到一个新的最小值,执行流程如下所示。 操作步骤1 入栈第一个元素,因为是第一个元素,因此最小值就是此元素的值。 操作步骤2 入栈第二个元素,如下图所示: 因为入栈的元素 3 比 8 小,所以先将栈中的原最小值 8 存入栈中,再将 3 入栈。 操作步骤3 入栈第三个元素,如下图所示:因为入栈元素 5 大于 3,因此栈中的最小值不变,直接将元素 5 入栈。 操作步骤4 继续入栈,如下图所示:入栈元素 1 小于于 3,因此先将原最小值 3 入栈,再将 1 入栈,栈中的最小值更改为 1。 操作步骤5 执行出栈操作,如下图所示:元素 1 出栈,判断当前元素就是栈的最小值,因此将栈顶元素 3 设置为最小值,并移除元素 3,如下图所示: 操作步骤6 继续出栈,如下图所示:因为元素 5 不是当前最小值,因此直接出栈。 操作步骤7 继续出栈,如下图所示:因为出栈元素 3 为最小值,因此继续将最小值设置为栈顶元素 8,并将栈顶元素出栈,如下图所示:这样就剩下最后一个元素了,最后一个元素出栈之后就成空栈了,整个流程就执行完了。 实现代码1 接下来我们将上面的思路用代码实现一下,我们用数组实现的栈来实现相关的功能,代码如下: classMinStack{privateint[]data;//栈数据privateintmaxSize;//最大长度privateinttop;//栈顶指针(下标)privateintmin;//最小值//构造函数publicMinStack(){//设置默认值maxSize=10000;data=newint[maxSize];top=-1;min=Integer.MAX_VALUE;}//入栈(添加元素)publicvoidpush(intx){if(min>=x){//遇到了更小的值,记录原最小值(入栈)data[++top]=min;min=x;}//当前值入栈data[++top]=x;}//出栈(移除栈顶元素)publicvoidpop(){if(min==data[top]){min=data[--top];//拿到原最小值,并(将原最小值)出栈}--top;//出栈}//查找栈顶元素publicinttop(){returndata[top];}//查询最小值publicintmin(){returnmin;}} 上述代码在 LeetCode 的执行结果如下: 可以看出性能还是很高的,超越了 99.92% 的用户,内存消耗也不大。它的核心代码在 push方法内,先将原最小值和最新最小值相继入栈,在 pop出栈时判断出栈元素是否为最小值,如果是最小值则将当前最小值指向栈顶元素并将栈顶元素出栈,这样就得到了下一个新的最小值了。 实现代码2 如果我们不想使用数组的自定义栈来实现,还可以使用 Java 中自带的栈 Stack来实现此功能,代码如下: classMinStack{privateStack<Integer>stack=newStack<>();privateintmin=Integer.MAX_VALUE;publicMinStack(){}//入栈(添加元素)publicvoidpush(intx){if(x<=min){//遇到了更小的值,记录原最小值(入栈)stack.push(min);min=x;}stack.push(x);}//出栈(移除栈顶元素)publicvoidpop(){if(stack.pop()==min){min=stack.pop();//取出原最小值}}//查找栈顶元素publicinttop(){returnstack.peek();}//查询最小值publicintmin(){returnmin;}} 上述代码在 LeetCode 的执行结果如下: 从结果可以看出,使用 Java 中自带的栈的性能不如自定义数组的栈,但代码还是通过了测试。这种实现方式的优点就是代码比较简单,可以利用了 Java 自身的 API 来完成了最小值的查找。 这种实现代码的方式(使用 Java API),在刷题或者实际面试中如果没有特殊说明是可以直接用的。 总结 本文我们通过两种方式:自定义数组栈和 Java API 中的 Stack来实现了栈中最小值的功能,保证了在调用栈的 min、push 及 pop 方法时的时间复杂度都是 O(1)。两种实现方式的代码虽然略不相同,但实现思路都是一样的,都是在元素入栈时判断当前元素是否小于最小元素,如果小于最小元素则先将原最小值入栈,再将当前最小元素入栈,这样当调用 pop 方法时,即使移除的是最小值,只需要将下一个元素取出即为新的最小值了,这样就可以实现调用 min、push 及 pop 方法时的时间复杂度都是 O(1) 了。 最后 机智的你一定还有其他的实现答案,评论区告诉我吧~ 原创不易,各位素质四联,谢啦。 往期推荐 链表反转的两种实现方法,后一种击败了100%的用户! JDK 竟然是这样实现栈的? 动图演示:手撸堆栈的两种实现方法! 关注下方二维码,收获更多干货! 本文分享自微信公众号 - Java中文社群(javacn666)。如有侵权,请联系 support@oschina.cn 删除。本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册