剑指offer---包含min函数的栈

🌏请代我向可爱的、温暖的太阳问好 ,向宁静的大海问好。
在这里插入图片描述

题目描述

定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。
题目链接:https://leetcode-cn.com/problems/bao-han-minhan-shu-de-zhan-lcof/

解题思路:

一看到这个题,我们的第一反应是在栈中添加一个成员遍历用来存放最小的元素。每次压入一个新元素进栈的时候,如果该元素比我们当前最小的元素还要小时,我们就更新最小元素,但是一旦我们当前最小的元素被弹出栈了,那么如何得到下一个最小的元素呢?

分析一番,我们发现仅仅在栈中添加一个成员变量来存储最小元素是完全不够的。所有我们希望能够得到次小元素的值。因此,在压入这个最小元素之前,我们要将次小元素保存起来。那么我们是不是可以将之前的最小元素和新压入栈的元素两者比较,将最小的值保存起来放入一个辅助栈中。

此题要求写一个栈,与普通栈不同的是多出了一个获取当前栈中的最小值函数min。由于栈比较简单,主要还是说说怎么以 O(1) 的时间复杂度查找栈中的最小值。

我们这里使用一个辅助栈m_minstatck来实现O(1)的复杂度。
1、数据栈m_data:用于存储所有元素,保证入栈 push() 函数、出栈 pop() 函数、获取栈顶 top() 函数的正常逻辑。

2、辅助栈m_minstatck:辅助栈中存放当前数据栈中的最小值。

**push():**将数据入栈的同时,更新最小值。如果入栈元素大于辅助栈顶元素(也就是元素入栈前,数据栈中的最小值),则最小值依旧是数据栈原来的最小值,否则将元素入辅助栈。
在这里插入图片描述

pop():我们将数据栈的元素和的对应的辅助栈中的最小值弹出栈。为什么辅助栈的元素也要跟着一起弹出呢。这是因为我们要维持两个栈中的元素个数相等,且每个数据栈中的元素对应每一个辅助栈中的对应位置的最小值。

在这里插入图片描述
top():用来返回数据栈的栈顶元素,即m_data.top()。
min():直接返回栈 m_minstatck的栈顶元素,即返回 m_minstatck.top() 。

算法效率

时间复杂度 O(1) : push()、pop()、top()、min() 四个函数的时间复杂度均为常数级别O(1)。
空间复杂度 O(N) : 当共有 n 个待入栈元素时,辅助栈m_minstatck在最差的情况下会存储 n 个元素,使用O(n) 额外空间。

解题代码

class MinStack 
{
public:
    /** initialize your data structure here. */
    MinStack() 
    {

    }
    
    void push(int x)
    {
        m_data.push(x);
		//如果当前为空,或者当前的x小于我们的辅助栈中最小的值则把x也压入辅助栈中
        if(m_minstack.empty()||m_minstack.top()>x)
        {
            m_minstack.push(x);
        }
        else
        {
            m_minstack.push(m_minstack.top());
        }
    }
    
    void pop() //弹出辅助栈和数据栈的元素
    {
        m_data.pop();
        m_minstack.pop();
    }
    
    int top() //返回栈顶元素
    {
        return m_data.top();
    }
    
    int min() //返回当前栈中最小的元素
    {
        return m_minstack.top();	
    }
    stack<int>m_data;	//数据栈,存放数据
    stack<int>m_minstack;	//辅助栈,存放当前不同时期的最小值
};

在这里插入图片描述

如有错误之处或有更优解,还请各位指出,谢谢大家!!!
END…

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值