首页 > 试题广场 >

最小栈

[编程题]最小栈
  • 热度指数:5633 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 128M,其他语言256M
  • 算法知识视频讲解
实现一个最小栈,有三种操作,min:得到栈中的最小值,push:在栈顶插入一个元素,pop:弹出栈顶元素,使这三种操作的时间复杂度都是O(1)
要求:语言不限

输入描述:
第一行是一个数Q,接下来Q行每行表示一个操作,每行首先是操作op
若op==0,则输出当前栈中的最小值;
若op==1,表示push,接着正整数x,把在x放进栈顶;
若op==2,表示pop,弹出栈顶元素
保证Q<=500000,保证op==0或2时(即min操作和pop操作时)栈不为空。
你可以假设一开始栈的空的。


输出描述:
对应每个op==0或2,如果是op==0输出当前栈中的最小值,如果是op==2输出弹出的元素。
示例1

输入

7
1 3
1 4
0
1 2
0
2
0

输出

3
2
2
3

说明

第一个操作为push 3,此时栈元素为3
第二个操作为push 4,此时栈元素为3,4
第三个操作为min,此时栈元素为3,4,输出最小值3
第四个操作为push 2,此时栈元素为3,4,2
第五个操作为min,此时栈元素为3,4,2,输出最小值2
第六个操作为pop,弹出元素2,此时栈元素为3,4,输出弹出的元素2
第七个操作为min,此时栈元素为3,4,输出最小值3

Java 欲哭无泪

您的代码已保存
运行超时:您的程序未能在规定时间内运行结束,请检查是否循环有错或算法复杂度过大。
case通过率为66.67%

可以用的方法都用了:

  • 法1:
    一个栈记录差值:这个方法所有操作都是O(1)根本不需要格外的辅助空间

  • 法2:
    使用一个辅助栈,记录最小值,所有操作也是O(1)

上述方法都使用过后,通过率都是66.67%
开始怀疑人生!
于是对第二种方法做了点点优化,通过数组手写一个栈(代码如下)

import java.util.*;
class MinStack{
    int[] array;
    int[] minArray;
    int index;
    public MinStack(int capacity){
        array=new int[capacity+5];
        minArray=new int[capacity+5];
        index=0;
        minArray[0]=Integer.MAX_VALUE;
    }
    public void push(int elem){
        array[++index]=elem;
        minArray[index]=Math.min(elem,minArray[index-1]);
    }
    public int pop(){
        index--;
        return array[index+1];
    }
    public int min(){
        return minArray[index];
    }
}
public class Main{
    public static void main(String[] args){
        MinStack minStack;
        int Q,op;
        Scanner in=new Scanner(System.in);
        Q=in.nextInt();
        minStack=new MinStack(Q);
        while(Q-->0){
            op=in.nextInt();
            if(op==0){
                System.out.println(minStack.min());
            }else if(op==1){
                minStack.push(in.nextInt());
            }else if(op==2){
                System.out.println(minStack.pop());
            }
        }
    }
}

没错,这次优化依旧没有什么*用,通过率还是66.67%
算了,思想了解了,不死磕!

发表于 2019-12-05 13:03:38 回复(4)
#include <bits/stdc++.h>
using namespace std;
int main()
{
    int q,op,x;
    cin>>q;
    stack<int>s1,s2;
    while(q--)
    {
        cin>>op;
        if(op==0)
            cout<<s2.top()<<endl;
        else if(op==1)
        {
            cin>>x;
            s1.push(x);
            if(s2.empty() || x <= s2.top()) 
                s2.push(x);
        }
        else if(op==2)
        {
            cout<<s1.top()<<endl;
            if(s1.top() == s2.top()) 
                s2.pop();
            s1.pop();
        }
    }
    return 0;
}

发表于 2019-07-10 20:53:10 回复(1)
/*
空间换时间,另设一个栈b记录最小值
*/
#include <bits/stdc++.h>
using namespace std;
stack<int> a, b;
int main()
{
    //freopen("input.txt", "r", stdin);
    int t, op, x;
    cin >> t;
    while(t--) {
        scanf("%d", &op);
        if(op == 1) {
            scanf("%d", &x);
            a.push(x);
            if(!b.empty()) b.push(min(b.top(), x));
            else b.push(x);
        } else if (op == 2) {
            printf("%d\n", a.top());
            a.pop();
            b.pop();
        } else {
            printf("%d\n", b.top());
        }
    }
    return 0;
}

发表于 2019-07-17 18:38:27 回复(0)
#include <bits/stdc++.h>
using namespace std;

int main(){
    int Q, op, x;
    cin>>Q;
    stack<int> S, S_min;
    while(Q--){
        cin>>op;
        if(op==0)
            cout<<S_min.top()<<endl;
        else if(op==1){
            cin>>x;
            S.push(x);
            if(S_min.empty() || x<=S_min.top())
                S_min.push(x);
        }else if(op==2){
            cout<<S.top()<<endl;
            if(S.top() == S_min.top())
                S_min.pop();
            S.pop();
        }
    }
    return 0;
}

发表于 2019-12-19 23:53:48 回复(0)
#include <stdio.h>
#include <iostream>

using namespace std;

struct Stack {
	int *a;
	int *Min;
	int index;
	int mindex;
	Stack(int n) {
		a = new int [n + 1];
		Min = new int [n + 1];
		index = 0;
		mindex = 0;
		for (int i = 0; i < n; i++) {
			Min[i] = (int)1e9 + 10;
		}
	}
	~Stack() {
		delete []a;
		delete []Min;
	}
	void push(int val) {
		if (val <= Min[mindex]) {
			Min[++mindex] = val;
		}
		a[++index] = val;
	}
	int pop() {
		int temp = a[index];
		index--;
		if (temp == Min[mindex]) {
			mindex--;
		}
		return temp;
	}
	int query() {
		return Min[mindex];
	}
};

const int N = (int)5e5 + 10;

int main() {
	Stack st(N);
	int tt;
	scanf("%d", &tt);
	while (tt--) {
		int op;
		scanf("%d", &op);
		if (op == 1) {
			int val;
			scanf("%d", &val);
			st.push(val);
		} else if (op == 0) {
			printf("%d\n", st.query());
		} else {
			printf("%d\n", st.pop());
		}
	}
	return 0;
}

发表于 2019-11-22 15:22:34 回复(0)
import java.util.Scanner;
import java.util.Stack;


class MinStack{
    // 最小栈,存入栈中的元素的一个数组,长度为2,一个是入栈的元素,另一个是之前入栈内的最小元素
    //数组栈, [当前值, 当前最小值]
    private Stack<int[]> stack = new Stack<>();
    // 构造方法
    public MinStack(){};

    // push方法
    public void push(int val){
        if(stack.isEmpty()){
            stack.push(new int[]{val, val});
        }else{
            stack.push(new int[]{val, Math.min(val, stack.peek()[1])});
        }
    }

    // pop方法
    public int pop(){
        return stack.pop()[0];
    }

    // getMin方法
    public int getMin(){
        return stack.peek()[1];
    }

}
// https://www.nowcoder.com/practice/a4d17eb2e9884359839f8ec559043761
public class Main {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int Q, op;
        Q = in.nextInt();
        MinStack minStack = new MinStack();
        for(int i = 0; i < Q; i++){
            op = in.nextInt();
            if(op == 0){
                System.out.println(minStack.getMin());
            }else if(op == 1){
                minStack.push(in.nextInt());
            }else if(op == 2){
                System.out.println(minStack.pop());
            }
        }
    }
}

发表于 2022-02-17 01:09:20 回复(0)
用两个栈实现,两个栈中的元素位置保持同步,其中一个栈是正常的栈,另一个是最小栈,最小栈的特点是始终保持栈顶是当前栈中最小的元素。
(1) 压栈时,最小栈会先检查此时要压入的元素是否比栈顶小,小就直接压入,大就仍然压入栈顶元素,表示这次压栈并未改变栈中元素的最小值。
(2) 弹栈时,两个栈都弹栈即可。
(3) 求最小值时,返回最小栈的栈顶即可。
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.Stack;

class MinStack {
    private Stack<Integer> stack = new Stack<>();
    private Stack<Integer> minStack = new Stack<>();
    public void push(int val) {
        stack.push(val);
        if(minStack.isEmpty()){
            minStack.push(val);
        }else{
            if(val < minStack.peek())
                minStack.push(val);
            else
                minStack.push(minStack.peek());
        }
    }
    
    public int pop() {
        minStack.pop();
        return stack.pop();
    }
    
    public int min() {
        return minStack.peek();
    }
}

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        MinStack stack = new MinStack();
        int n = Integer.parseInt(br.readLine().trim());
        for(int i = 0; i < n; i++){
            String[] params = br.readLine().trim().split(" ");
            int op = Integer.parseInt(params[0]);
            if(op == 0){
                System.out.println(stack.min());
            }else if(op == 2){
                System.out.println(stack.pop());
            }else
                stack.push(Integer.parseInt(params[1]));
        }
    }
}

发表于 2021-04-12 17:59:50 回复(0)
一,输出不直接用System.out.println,用StringBuilder,最后一次全部输出。如果这还超时,只好考虑下一步
二,输入改用new StreamTokenizer((new BufferedReader(new InputStreamReader(System.in))))
发表于 2021-03-19 13:59:10 回复(0)
#include<iostream>
#include<stack>
using namespace std;
class Solution{
public:
    int getmin(){
        return op2.top();
    }
    void push(int x){
        if(op1.empty()){
            op1.push(x);
            op2.push(x);
        }else{
            op1.push(x);
            if(x <= op2.top())
                op2.push(x);
        }
    }
    void pop(){
        if(!op1.empty()){
            int tmp = op1.top();
            if(tmp == op2.top())
                op2.pop();
            
            op1.pop();
            cout << tmp << endl;
        }
    }
private:
    stack<int> op1;
    stack<int> op2;
};
int main()
{
    Solution a;
    int x;
    cin >> x;
    while(x--){
        int op;
        cin >> op;
        if(op == 0){
            cout << a.getmin() << endl;
        }else if(op == 2){
            a.pop();
        }else if(op == 1){
            int t;
            cin >> t;
            a.push(t);
        }
    }
    return 0;
}

发表于 2020-12-06 17:27:33 回复(0)
实现思路:栈顶元素和栈中的最小值组合成一个整体,一个对象。
但本题的测试数据集非常庞大,I/O读取耗时会成为性能瓶颈点,也是本题的难点所在。因为当程序运行没通过时,大家都以为是实现逻辑有问题,而不是运行超时了。

import java.io.*;
import java.util.*;
 
/**
 * <a href="https://www.nowcoder.com/questionTerminal/a4d17eb2e9884359839f8ec559043761">
 *     最小栈</a>
 *
 * @author EdwardLee03
 * @since 2020-03-22
 */
public class Main {
    private static class StackElement {
        /**
         * 值
         */
        int value;
        /**
         * 最小值
         */
        int min;
    }
 
    /** 值栈 */
    private Deque<StackElement> deque;
 
    public Main() {
        deque = new LinkedList<>();
    }
 
    public void push(int x) {
        StackElement se = new StackElement();
        se.value = x;
        if (deque.isEmpty() || deque.peekFirst().min >= x) {
            se.min = x;
        } else {
            se.min = deque.peekFirst().min;
        }
        deque.offerFirst(se);
    }
 
    public int pop() {
        if (deque.isEmpty()) {
            return  0;
        }
        return deque.pollFirst().value;
    }
 
    public int min() {
        if (deque.isEmpty()) {
            return 0;
        }
        return deque.peekFirst().min;
    }
 
    public static void main(String[] args) throws IOException {
        Main minStack = new Main();
 
        StreamTokenizer streamTokenizer = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
        streamTokenizer.nextToken();
        int lineNum = (int) streamTokenizer.nval;
        // 通过缓冲器优化IO输出打印
        StringBuilder sb = new StringBuilder(lineNum * 4);
        while (lineNum-- > 0) {
            streamTokenizer.nextToken();
            int op = (int) streamTokenizer.nval;
            switch (op) {
                case 1:
                    streamTokenizer.nextToken();
                    int e = (int) streamTokenizer.nval;
                    minStack.push(e);
                    break;
                case 0:
                    sb.append(minStack.min()).append('\n');
                    break;
                case 2:
                    sb.append(minStack.pop()).append('\n');
                    break;
            }
        }
        System.out.println(sb.toString().trim());
    }
}


编辑于 2020-05-05 00:02:56 回复(4)
/*40%,在哪里会数组越界,求解答*/

import java.util.*;
class minStack{
    public Stack<Integer> stack = new Stack<Integer>();
    public Stack<Integer> min = new Stack<Integer>();
    public int minval = 0;
    public int pop(){
        int k = 0;
        if(!stack.isEmpty()){
            k=stack.pop();
            min.pop();
            minval = min.peek();
            return k;
        }
        else{
            return -1;
        }
    }
    public void push(int val){
        if(stack.isEmpty()){
            minval = val;
        }else{
            if(val<minval){
                minval = val;
            }
        }
        stack.push(val);
        min.push(minval);
    }
    public int getMin(){
        if(!stack.isEmpty()){
            return min.peek();
        }else{
            return -1;
        }
    }
}
public class Main{
    public static void main(String[] args){
        minStack mmm = new minStack();
        Scanner sc = new Scanner(System.in);
        int Q= sc.nextInt();
        int k = 0;
        int m = 0;
        for(int i = 0;i<Q;i++){
            sc.nextLine();
            k = sc.nextInt();
            if(k == 0){
                System.out.println(mmm.getMin());
            }
            if(k == 1){
                m = sc.nextInt();
                mmm.push(m);
            }
            if(k == 2){
                System.out.println(mmm.pop());
            }
        }
    }
}

发表于 2020-04-02 23:00:10 回复(1)
Deque stack=new LinkedList();
    
    public void push(int i) {
        
        stack.push(i);
        
    }
    
public void pop() {
        
    System.out.println(stack.pop());
        
    }
public void zz() {
    int n=stack.size();
    
    int []arry=new int[n];
    
    for(int i=0;i<n;i++) {
        
        
        arry[i]=(Integer) stack.pop();
        stack.push(arry[i]);
        
        
    }
        
        for(int i=0;i<n-1;i++) {
            int k;
            for(int y=1;y<=n-2;y++) {
                if(arry[i]>arry[y]) {
                    k=arry[i];
                    arry[i]=arry[y];
                    arry[y]=k;
                    
                    
                    
                    
                }
                
                
                
                
                
            }
            
            
            
        }
        
        
        
        
    
    
    System.out.println(arry[0]);
发表于 2020-03-14 08:27:40 回复(0)
import java.util.*;

public class Main{
static Stack<Integer> minStack = new Stack<Integer>();
static Stack <Integer> stack = new Stack<Integer>();
public static void main(String [] args){
minStack.push(Integer.MAX_VALUE);
Scanner input = new Scanner(System.in);
int Q = input.nextInt();
while(Q-- > 0){
int op = input.nextInt();
if(op == 0){
System.out.println(getMinStackValue());
}else if(op == 1){
Integer pushValue = input.nextInt();
compareMinStack(pushValue);
stack.push(pushValue);
}else{
minStack.pop();
System.out.println(stack.pop());
}

}
}

public static Integer getMinStackValue(){
return minStack.lastElement();
}

public static void compareMinStack(Integer value){
Integer min = getMinStackValue();
if(value < min){
minStack.push(value);
}else{
minStack.push(min);
}
}
}

emmm运行超时了,通过率只有66.67%,看看大佬们有没有什么优化建议。
编辑于 2020-03-01 14:20:15 回复(1)
c++ 单个栈操作
class MinStack{
    public:
        MinStack()
        {
            minNum = 0x7fffffff;
        }
        void push(int val)
        {
            if(val <= minNum){
                stk.push(minNum);
                minNum = val;
            }
            stk.push(val);
        }
    
        int pop(void)
        {
            int val = stk.top();
            stk.pop();
            if(val == minNum){
                minNum = stk.top();
                stk.pop();
            }
            return val;
        }
    
        int min(void)
        {
            return minNum;
        }
    private:
        stack<int, vector<int> > stk;
        int minNum;
};


int main(void)
{
    int q , opCode = 0, opVal = 0;
    MinStack stk;
    cin >> q;
    while(q-- > 0)
    {
        cin >> opCode;
        switch(opCode)
        {
            case 0:
                cout << stk.min() << endl;
                break;
            case 1:
                cin >> opVal;
                stk.push(opVal);
                break;
            case 2:
                cout << stk.pop() << endl;
                break;
        }
    }
}


发表于 2019-11-04 18:23:43 回复(0)
求debug~

#include<iostream>

#include<stack>
using namespace std;




int main() {
    stack<int> s,s_min;
    int n, one,first, x, op;
    cin >> n;
    cin >> one >> first;
    s.push(first);
    s_min.push(first);
    for (int i = 1; i < n; i++) {
        cin >> op;
        if (op == 0) {
            cout << s_min.top()<<endl;
        }
        else if (op == 1) {
            cin >> x;

            s.push(x);
            if (x <= s_min.top())
            s_min.push(x);
        }
        else
        {
            if (s.top() == s_min.top()) {
                s_min.pop();
            }
            cout << s.top()<<endl;
            s.pop();
        }
}

return 0;
}

发表于 2019-10-13 17:34:55 回复(1)
class MyStack:
    def __init__(self):
        self.st_data = []
        self.st_min = []
    
    def push(self, node):
        self.st_data.append(node)
        if not self.st_min or node < self.st_min[-1]:
            self.st_min.append(node)
        else:
            self.st_min.append(self.st_min[-1])
    
    def pop(self):
        self.st_min.pop()
        return self.st_data.pop()
    
    def get_min(self):
        return self.st_min[-1]


st = MyStack()
Q = input()
for i in range(Q):
    #lst = input().split()
    #op = int(lst[0])
    op = raw_input()
    if op == "0":
        print(st.get_min())
    elif op == "2":
        print(st.pop())
    else:
        st.push(int(op[2:]))

发表于 2019-09-06 20:48:17 回复(0)
#include <iostream>
#include <stack>
using namespace std;
stack<int> stack1,stack2;

void push(int value)
{
    stack1.push(value);
    if(stack2.empty())
        stack2.push(value);
    else if(value<=stack2.top())
        stack2.push(value);
}
int pop()
{
    if(stack1.top()==stack2.top())
        stack2.pop();
    int res=stack1.top();
    stack1.pop();
    return res;
}
int min()
{
    return stack2.top();
}
int main()
{
    int Q;
    cin >>Q;
    for(int i=0;i<Q;i++)
    {
        int op,x;
        cin>>op;
        if(op==0&& !stack1.empty())
            cout<<min()<<endl;
        if(op==1)
        {
            int x;
            cin >>x;
            push(x);
        }
        if(op==2&& !stack1.empty())
            cout<<pop()<<endl;
    }
    return 0;
}

发表于 2019-09-06 01:11:55 回复(0)
用了一个二维数组来存输入的值..
#include<iostream>
#include<stack>
#include<vector>
using namespace std;

int main() {
	stack<int> stack1;
	stack<int> stack2;
	int Q;
	cin >> Q;
	int** a = new int*[Q];
	for (int i = 0; i < Q; i++)
		a[i] = new int[2];
	for (int i = 0; i < Q; i++)
		for (int j = 0; j < 2; j++)
			a[i][j] = 0;

	for (int i = 0; i < Q; i++)
	{
		cin >> a[i][0];
		if (a[i][0] == 1)
			cin >> a[i][1];
	}
	//
	for (int i = 0; i < Q; i++)
	{
        //push
		if (a[i][0] == 1)
		{
			stack1.push(a[i][1]);
			if (!stack2.empty())
			{
				if(a[i][1] <= stack2.top())
					stack2.push(a[i][1]);
			}
			else
				stack2.push(a[i][1]);
		}	
        //pop
		else if (a[i][0] == 2)
		{
			int tmp = stack1.top();
			if (tmp == stack2.top())
				stack2.pop();
			stack1.pop();
			cout << tmp << endl;
		}
        //min
		else
		{
			int min = stack2.top();
			cout << min << endl;
		}
	}
	return 0;
}


发表于 2019-09-05 09:55:15 回复(0)
#include<iostream>
#include<stack>
using namespace std;
class MinStack{
public:
    MinStack(){}
    void push(int value){
        _sss.push(value);
        if(_min.empty() || _min.top() > value)
            _min.push(value);
    }
    int pop(){
        if(_min.top() == _sss.top())
            _min.pop();
        int num =  _sss.top();
        _sss.pop();
        return num;
    }
    int min(){
        return _min.top();
    }
private:
    stack<int> _sss;
    stack<int> _min;
};
int main(){
    int Q = 0;
    MinStack s;
    cin >> Q;
    for(int i = 0;i < Q;++i){
        int op = 0;
        cin >> op;
		if (op == 0) {
			cout << s.min() << endl;
		}
		else if (op == 1)
		{
            int op2 = 0;
            cin >> op2;
			s.push(op2);
		}
		else if (op == 2)
		{
			cout << s.pop() << endl;
		}
	}
    return 0;
}
不通过
您的代码已保存
段错误:您的程序发生段错误,可能是数组越界,堆栈溢出(比如,递归调用层数太多)等情况引起
case通过率为73.33%

估计是超时了
发表于 2019-08-29 20:27:45 回复(1)
有个问题 栈的pop不是不返回值吗?? 题目不说清楚 要是考试模式碰到的  鬼知道为什么错了
这太坑了
#include <iostream>
#include <stack>
using namespace std;

class ministack
{
  private:
    stack<int> sdata;
    stack<int> sass;
  public:
   void push(int value)
   {
       if(sdata.empty())
       {
           sdata.push(value);
           sass.push(value);
       }
       else
       {
           int mini = sass.top();
           if(value<mini)
           {
               sass.push(value);
           }
           else
           {
               sass.push(mini);
           }
           sdata.push(value);
       }
       
   }
   int pop()
   {
       if(!sdata.empty())
       {
           int data = sdata.top();
           sdata.pop();
           sass.pop();
           return data;
       }
   }
    int min()
    {
        if(!sdata.empty())
        {
            return sass.top();
        }
    }
    
    
};

int main()
{
    int times =0;
    cin>>times;
    ministack m;
    for(int i =0;i<times;i++)
    {
        int op;
        cin>>op;
        if(op==0)
        {
            cout<<m.min()<<endl;
        }
        if(op==1)
        {
            int data;
            cin>>data;
            m.push(data);
        }
        if(op==2)
        {
            cout<<m.pop()<<endl;;
        }
    }
    
    
    return 0;
}

编辑于 2019-08-19 20:33:41 回复(0)