MinStackOPT [source code]


public class MinStackOPT {
static
/******************************************************************************/
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;
    }
}
/******************************************************************************/

    public static void main(String[] args) {
        MinStackOPT.MinStack minStack = new MinStackOPT.MinStack();
        minStack.push(-2);
        minStack.push(0);
        minStack.push(-3);
        System.out.println(minStack.getMin()); //-3
        minStack.pop();
        System.out.println(minStack.top()); //0
        System.out.println(minStack.getMin()); //-2
    }
}

这个是discussion上面的一个最优解, 非常聪明:

作者原话:
The question is ask to construct One stack. So I am using one stack.

The idea is to store the gap between the min value and the current value;

The problem for my solution is the cast. I have no idea to avoid the cast. Since the possible gap between the current value and the min value could be Integer.MAX_VALUE-Integer.MIN_VALUE;


仔细思考一下这个问题, 想知道我这个问题没有做出来到底反映出来我哪些问题;

首先, 做算法题, 最终要追求的一个目的是, 碰到一个完全没有现成模板可以套的题目的时候, 要能冷静的分析面临的困难是什么? 为什么我现在的算法(有时候是笨算法)为什么做不了? 然后你能够根据这个面临的困难, 快速从长期的训练的记忆当中找到合适的应对办法;

纵观这个题目的几个最优解, 其实这个题目本身是一个挺典型的historial stream问题; 当你面临一个pop的时候, 你的困难是, 当你pop掉的是一个min的时候, 你不知道下一个min是什么? 解决这个问题的关键就是怎样保存之前的历史信息; 这个就有点像2sum里面: 当你走到一个数字的时候, 你不知道之前的数字跟这个数字是否有可以组合的.
为了防止后面的(或者说现在的)iteration不知道, 我们在之前的iteration就要存. 这题的核心思想就是这样.
至于具体怎么存, 方法就很多;
最直白的就是wrapper的思路和2stacks的思路. 这两个思路其实都挺中规中矩的, 可惜我一个都没有想到;
当然push min和push gap这两个思路其实就比较难想一点, 但是实际上的本质都是一个store historial information的思路;

另外一个角度: 我们这个题目, 想了这么多, 其实目的就很简单, 就是想要做到O(1)的时间复杂度(指的是某一个operation, 如果是N个operation, 那么我们追求的复杂度其实就是O(N): 处理每一个operation的时间是O(1)), 这个以前也是总结过的, 加速到O(1), 一般的思路也就那么几个. 这里用的就是历史信息处理的方法; 注意, 这里讨论的是加速到O(1), 是指你知道简单的思路无法做到O(1)的情况下, 想要加速, 这个时候你有什么思路;

另外, 这里push gap的思路其实是最优秀的, 因为它要求存储的信息最少;
wrapper and 2stacks其实是每一个value都要对应的存储一个min, 这个其实是没有必要的, 当然维护起来更方便罢了;
push min的思路, 其实space跟上面这俩是差不多的;
只有push gap这个思路, 真正做到了, 只记录the point where min is actually changed.

感觉这个解还是要多酝酿一下, 暂时还是不理解其背后隐含的思考方式;


这个是discussion上面另外一个最优解:

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;  
    }  
}

没有上面那个slick, 但是想法本身也是很好的, 这里避免计算的手段, 可以理解为类似DP里面的memo;
在data structure的context里来应用这个思想确实也是第一次见到;


Problem Description

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(); .
minStack.pop();
minStack.top();
minStack.getMin(); .
Difficulty:Easy
Total Accepted:132.3K
Total Submissions:468.1K
Contributor: LeetCode
Companies
google uber zenefits amazon snapchat bloomberg
Related Topics
stack design
Similar Questions
Sliding Window Maximum

/**

  • Your MinStack object will be instantiated and called as such:
  • MinStack obj = new MinStack();
  • obj.push(x);
  • obj.pop();
  • int param_3 = obj.top();
  • int param_4 = obj.getMin();
    */

results matching ""

    No results matching ""