刷题打卡——栈的最小值、化栈为队

154 阅读3分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

第一题:栈的最小值

一、题目描述:

请设计一个栈,除了常规栈支持的pop与push函数以外,还支持min函数,该函数返回栈元素中的最小值。执行push、pop和min操作的时间复杂度必须为O(1)。

示例:

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

二、思路分析:

这题的解答我这里使用的是辅助栈。

创建两个栈,一个常规栈和一个始终保持最小值在栈顶的栈。初始化时,将Integer.MAX_VALUE放到最小栈中,这里存Integer.MAX_VALUE主要是为了减少栈为空时push操作的判断。

push方法:常规栈正常push,辅助栈压栈的值为辅助栈栈顶和当前值的最小值minStack.push(Math.min(minStack.peek(),x)),这样保证了辅助栈栈顶元素永远是所有值中的最小值。

pop方法:常规栈和辅助栈同时pop()。

top方法:返回常规栈的栈顶元素。

getMin方法:返回辅助栈的栈顶元素。

三、AC 代码:

class MinStack {
    Stack<Integer> stack;
    Stack<Integer> minStack;
    /** initialize your data structure here. */
    public MinStack() {
        stack = new Stack();
        minStack = new Stack();
        minStack.push(Integer.MAX_VALUE);
    }
    
    public void push(int x) {
        stack.push(x);
        minStack.push(Math.min(minStack.peek(),x));
    }
    
    public void pop() {
        stack.pop();
        minStack.pop();
    }
    
    public int top() {
        return stack.peek();
    }
    
    public int getMin() {
       return minStack.peek();
    }
}

/**
 * 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();
 */

第二题:化栈为队

一、题目描述:

实现一个MyQueue类,该类用两个栈来实现一个队列。

示例:

MyQueue queue = new MyQueue();

queue.push(1);
queue.push(2);
queue.peek();  // 返回 1
queue.pop();   // 返回 1
queue.empty(); // 返回 false

说明:

  • 你只能使用标准的栈操作 -- 也就是只有 push to top, peek/pop from top, size 和 is empty 操作是合法的。
  • 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可
  • 假设所有操作都是有效的 (例如,一个空的队列不会调用 pop 或者 peek 操作)。

二、思路分析:

两个栈实现一个队列,这个是一个比较经典的问题。

思路很简单,主要是实现pop方法。

我们知道栈是后进先出,队列是先进先出,那么使用两个栈,第一次进栈元素出栈后顺序反了,再进一次栈出栈后顺序就成了最开始的顺序。

注意点:第二个栈里面元素不为空时队列头元素就是栈顶元素,当第二个栈为空时就需要将第一个栈的所有元素放到栈2中,这样才能保证元素有序。

三、AC 代码:

class MyQueue {
    Deque<Integer> stack_one;
    Deque<Integer> stack_two;
    /** Initialize your data structure here. */
    public MyQueue() {
        stack_one = new LinkedList<Integer>();
        stack_two = new LinkedList<Integer>();
    }
    
    /** Push element x to the back of queue. */
    public void push(int x) {
        stack_one.push(x);
    }
    
    /** Removes the element from in front of queue and returns that element. */
    public int pop() {
        if(!stack_two.isEmpty()){
            return stack_two.pop();
        }else if(!stack_one.isEmpty()){
            while(!stack_one.isEmpty()){
                stack_two.push(stack_one.pop());
            }
            return stack_two.pop();
        }else{
            return -1;
        }
    }
    
    /** Get the front element. */
    public int peek() {
        if(!stack_two.isEmpty()){
            return stack_two.peek();
        }else if(!stack_one.isEmpty()){
            while(!stack_one.isEmpty()){
                stack_two.push(stack_one.pop());
            }
            return stack_two.peek();
        }else{
            return -1;
        }
    }
    
    /** Returns whether the queue is empty. */
    public boolean empty() {
        return stack_one.isEmpty() && stack_two.isEmpty();
    }
}

/**
 * Your MyQueue object will be instantiated and called as such:
 * MyQueue obj = new MyQueue();
 * obj.push(x);
 * int param_2 = obj.pop();
 * int param_3 = obj.peek();
 * boolean param_4 = obj.empty();
 */