LeetCode Stack Design专题

LeetCode Stack / Design专题专题部分,更多说明请见LeetCode Array专题

232. Implement Queue using Stacks

Implement the following operations of a queue using stacks.

  • push(x) – Push element x to the back of queue.
  • pop() – Removes the element from in front of queue.
  • peek() – Get the front element.
  • empty() – Return whether the queue is empty.

Notes:

  • You must use only standard operations of a stack – which means only push to toppeek/pop from topsize, and is empty operations are valid.
  • Depending on your language, stack may not be supported natively. You may simulate a stack by using a list or deque (double-ended queue), as long as you use only standard operations of a stack.
  • You may assume that all operations are valid (for example, no pop or peek operations will be called on an empty queue).

译:使用栈来实现一个拥有以下操作的队列:

  • push(x) – Push element x to the back of queue.
  • pop() – Removes the element from in front of queue.
  • peek() – Get the front element.
  • empty() – Return whether the queue is empty.

注意:

你必须仅仅使用标准的栈操作,意味着存在这几个可用的操作:push到栈顶,从栈顶peek/pop,size和is empty操作

实现

public class TwoQueueUsingStacks {
    
    

    Stack<Integer> stackA = new Stack<>();
    Stack<Integer> stackB = new Stack<>();

    // Push element x to the back of queue.
    public void push(int x) {
        stackA.push(x);
    }

    // Removes the element from in front of queue.
    public void pop() {
        if (stackB.empty()) {
            while (!stackA.isEmpty()) {
                stackB.push(stackA.pop());
            }
        }
        stackB.pop();
    }

    // Get the front element.
    public int peek() {
        if (stackB.empty()) {
            while (!stackA.isEmpty()) {
                stackB.push(stackA.pop());
            }
        }
        return stackB.peek();
    }

    // Return whether the queue is empty.
    public boolean empty() {
        return (stackA.empty()) && (stackB.empty());
    }
}

问题分析

先画图,画分解图一步步的通过入栈出栈LIFO的特性就能反推出链表FIFO的行为,例如存在两个栈A 、B,将一组元素{a, b, c, d, e, f, g, h} 进行各种链表操作,只要遵循FIFO的行为就不难理解。

225. Implement Stack using Queues

Implement the following operations of a stack using queues.

  • push(x) – Push element x onto stack.
  • pop() – Removes the element on top of the stack.
  • top() – Get the top element.
  • empty() – Return whether the stack is empty.

Notes:

  • You must use only standard operations of a queue – which means only push to backpeek/pop from frontsize, and is empty operations are valid.
  • Depending on your language, queue may not be supported natively. You may simulate a queue by using a list or deque (double-ended queue), as long as you use only standard operations of a queue.
  • You may assume that all operations are valid (for example, no pop or top operations will be called on an empty stack).

Update (2015-06-11):
The class name of the Java function had been updated to MyStack instead of Stack.

译:使用队列来实现以下栈的操作:

  • push(x) – Push element x onto stack.
  • pop() – Removes the element on top of the stack.
  • top() – Get the top element.
  • empty() – Return whether the stack is empty.

实现

方法一:队列A负责入栈,队列B负责中转A中的元素

以下实现方式有个不足之处就是每次B不为空时,都需要将B中的所有元素遍历一遍传给A后在A中进行相关操作,导致效率低下。

class MyStack {

    LinkedList<Integer> queueA = new LinkedList<>();
    LinkedList<Integer> queueB = new LinkedList<>();

    // Push element x onto stack.
    public void push(int x) {
        if (queueB.isEmpty()) {
            queueA.add(x);
        } else {
            queueB.add(x);
        }
    }

    // Removes the element on top of the stack.
    public void pop() {
        if (queueA.isEmpty() && queueB.isEmpty()) {
            return;
        }
        if (queueB.isEmpty()) {
            while(queueA.size() > 1) {
                queueB.add(queueA.remove());
            }
            if (queueA.size() > 0) {
                queueA.remove();
            }
        } else {
             while(queueB.size() > 1) {
                queueA.add(queueB.remove());
             }
            if (queueB.size() > 0) {
                queueB.remove();
            }
        }
    }

    // Get the top element.
    public int top() {
        if(queueA.isEmpty() && queueB.isEmpty()) {
            return 0;
        }

        if (queueB.isEmpty()) {
            while(queueA.size() > 1) {
                queueB.add(queueA.remove());
            }
            int lastElement = queueA.peek();
            queueB.add(queueA.remove());
            return lastElement;
        } else {
            while(queueB.size() > 1) {
                queueA.add(queueB.remove());
            }
            int lastElement = queueB.peek();
            queueA.add(queueB.remove());
            return lastElement;
        }
    }

    // Return whether the stack is empty.
    public boolean empty() {
        return (queueA.isEmpty() && queueB.isEmpty());
    }
}

问题分析

关于栈和队列的相互实现,主要考察的是两者的概念和原理的清晰度,并且在队列实现中,需要了解相关语言的知识点,例如Java中实现队列结构的类有LinkedList,那么LinkedList中的哪些方法符合条件,就可以去看看Java源码。这里给出LeetCode中对这次的总结,各类操作的时间复杂度都分析明确,值得仔细看看:implement-stack-using-queues

155. Min Stack

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.

译:设计一个支持push / pop / top操作的栈,能够在常量时间取得最小值

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.

实现

public class MinStack {
    
    

    Stack<Integer> minValueStack = new Stack<>();
    Stack<Integer> mStack = new Stack<>();

    public void push(int x) {
        mStack.push(x);
        if (minValueStack.isEmpty() || minValueStack.peek() >= x) {
            minValueStack.push(x);
        }
    }

    public void pop() {
        if (mStack.isEmpty()) return;
        else {
            if (!minValueStack.isEmpty()) {
                if (mStack.peek().equals(minValueStack.peek())) {
                    minValueStack.pop();
                }
            }
            mStack.pop();
        }
    }

    public int top() {
        if (!mStack.isEmpty()) {
            return mStack.peek();
        } else return 0;
    }

    public int getMin() {
        if (minValueStack.isEmpty()) return 0;
        else return minValueStack.peek();
    }
}

问题分析

题中为了取当前栈mStack中最小值,一开始想的是用常量来做一个缓存,但发现最小值是根据栈mStack的内容动态变化的,这就意味着需要一个额外的栈minValueStack进行缓存。别的就是正常的栈操作,注意边界和空栈的情况即可。不过发现一个问题,如果原始栈一直处于递减状态,那么栈minValueStack会一直递增花费更多的空间,而一旦题目对空间的要求比较苛刻,这种方式就不再适用。

猜你喜欢

转载自blog.csdn.net/zxccxzzxz/article/details/53984292