leetcode#155. Min Stack

57 篇文章 0 订阅
14 篇文章 0 订阅

题目

Design a stack that supports push, pop, top, and retrieving the minimum element in constant time.

push(x) – Push element x onto stack.
pop() – Removes the element on top of the stack.
top() – Get the top element.
getMin() – Retrieve the minimum element in the stack.
Example:

MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin();   --> Returns -3.
minStack.pop();
minStack.top();      --> Returns 0.
minStack.getMin();   --> Returns -2.

思路

初始思路很偷懒,别的操作都好说,getmin的时候for循环查最短的元素。当然,会超时。看了下超时的用例,主要是一直在调用getmin,所以我将min的查询放到了push和pop中,getmin的时候直接return min。

代码

class MinStack(object):
    stack = []
    Min = False
    Minindex = False
    def __init__(self):
        """
        initialize your data structure here.
        """
        self.stack = []
        self.Min = False
        self.Minindex = False

    def push(self, x):
        """
        :type x: int
        :rtype: void
        """
        self.stack += [x]
        if type(self.Min) == type(False) or self.Min > x:
            self.Min = x
            self.Minindex = len(self.stack) - 1

    def pop(self):
        """
        :rtype: void
        """
        if self.stack:
            self.stack = self.stack[:-1]
            if not self.stack:
                self.Min = False
                self.Minindex = False
            elif type(self.Minindex) != type(False) and self.Minindex == len(self.stack):
                Min = self.stack[0]
                minIndex = 0
                for index, i in enumerate(self.stack):
                    if Min > i:
                        Min = i
                        minIndex = index
                self.Min = Min
                self.Minindex = minIndex

    def top(self):
        """
        :rtype: int
        """
        if self.stack:
            return self.stack[-1]

    def getMin(self):
        """
        :rtype: int
        """
        if self.stack:
            return self.Min


# Your MinStack object will be instantiated and called as such:
# obj = MinStack()
# obj.push(x)
# obj.pop()
# param_3 = obj.top()
# param_4 = obj.getMin()

过是过了,但是最佳算法肯定不是这么搞的呀!遂看了下discussion,发现以下几个有趣的算法。

代码一(作者reeclapple)

public class MinStack {
    long min;
    Stack<Long> stack;

    public MinStack(){
        stack=new Stack<>();
    }

    public void push(int x) {
        if (stack.isEmpty()){
            stack.push(0L);
            min=x;
        }else{
            stack.push(x-min);//Could be negative if min value needs to change
            if (x<min) min=x;
        }
    }

    public void pop() {
        if (stack.isEmpty()) return;

        long pop=stack.pop();

        if (pop<0)  min=min-pop;//If negative, increase the min value

    }

    public int top() {
        long top=stack.peek();
        if (top>0){
            return (int)(top+min);
        }else{
           return (int)(min);
        }
    }

    public int getMin() {
        return (int)min;
    }
}

这个算法的好处在于push的时候存x - min,如果结果小于0就更新min,pop的时候如果pop值小于0就更新min值,就可以恢复到除去pop值的min值。最后getmin的时候直接输出min值即可,不用遍历list

代码二(作者leftpeter2)

class MinStack
{
    static class Element
    {
        final int value;
        final int min;
        Element(final int value, final int min)
        {
            this.value = value;
            this.min = min;
        }
    }
    final Stack<Element> stack = new Stack<>();

    public void push(int x) {
        final int min = (stack.empty()) ? x : Math.min(stack.peek().min, x);
        stack.push(new Element(x, min));
    }

    public void pop()
    {
        stack.pop();
    }

    public int top()
    {
        return stack.peek().value;
    }

    public int getMin()
    {
        return stack.peek().min;
    }
}

这个算法更精巧,完全不用计算。只需更改下存入的数据结构。如代码所示,该数据结构中带有min值,存入x的时候同时会将当前的min值存入。这样的好处是无论何时,栈顶元素的min值肯定是当前栈的min值,而当元素pop出去后也不用重新计算新的min值,因为除去pop的那个元素后当前的min值还在栈顶的min中。

代码三(作者sometimescrazy)

class MinStack {
    int min = Integer.MAX_VALUE;
    Stack<Integer> stack = new Stack<Integer>();
    public void push(int x) {
        // only push the old minimum value when the current 
        // minimum value changes after pushing the new value x
        if(x <= min){          
            stack.push(min);
            min=x;
        }
        stack.push(x);
    }

    public void pop() {
        // if pop operation could result in the changing of the current minimum value, 
        // pop twice and change the current minimum value to the last minimum value.
        if(stack.pop() == min) min=stack.pop();
    }

    public int top() {
        return stack.peek();
    }

    public int getMin() {
        return min;
    }
}

这个答案也很不错,存x的时候如果要更新min值,就将min值也存入stack中,pop的时候如果pop值等于min,则min等于stack再次pop出来的值。总的来说就是min值更新的时候将之前的min值也存入stack中,pop的是min值时则恢复之前的min值。缺点就是最坏情况的时候空间占用会比较多。

总结

学到了3种有意思的算法,收获不少,以后也要每做一题都看看discussion学习学习。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值