其他栈相关问题

来源:互联网 发布:js获取对象数组的长度 编辑:程序博客网 时间:2024/06/03 18:05

1. 包含min函数的栈

来源
leetcode155 https://leetcode.com/problems/min-stack/
剑指offer21

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正常来说肯定是常数时间内的,但是如何让getMin也能保持在常数时间呢。
单独维护一个单调递减栈来存储栈中最小值。

class MinStack {    Deque<Integer> deque = new ArrayDeque<Integer>();    Deque<Integer> minDeque = new ArrayDeque<Integer>();    public void push(int x) {        deque.add(x);        if(minDeque.size() == 0 || x <= minDeque.peekLast()) minDeque.add(x);    }    public void pop() {        int x = deque.pollLast();        if(x == minDeque.peekLast()) minDeque.pollLast();    }    public int top() {        return deque.peekLast();    }    public int getMin() {        return minDeque.peekLast();    }}

2. 用两个栈实现队列

维护两个栈,每次Push进一个栈中,每次getHead从另一个栈中取,当取栈空了,则将push栈中的弹入取栈中。这样保证了先进的一定比后进的先出。弹出元素的平均时间复杂度O(1)

class QueueImpl {    Deque<Integer> deque_push = new ArrayDeque<Integer>();    Deque<Integer> deque_pop = new ArrayDeque<Integer>();    public void push(int x) {        deque_push.add(x);    }    public int getHead() {        if(deque_pop.size() == 0){                while(deque_push.size() != 0) deque_pop.add(deque_push.pollLast());        }        return deque_pop.pollLast();    }}

3. 用两个队列实现栈

维护两个队列,每次向有元素的队列压入元素(两个队列会交替压入),每次弹出元素时要将有元素队列中的元素放入另一个队列中,留下一个元素在原来的队列弹出。弹出的平均时间复杂度O(n)。

class StackImpl {    Deque<Integer> deque1 = new ArrayDeque<Integer>();    Deque<Integer> deque2 = new ArrayDeque<Integer>();    public void push(int x) {        Deque<Integer> deque = deque1.size() == 0 ? deque2 : deque1;        deque.add(x);    }    public int pop() {        Deque<Integer> deque_pop = deque1.size() == 0 ? deque2 : deque1;        Deque<Integer> deque_push = deque1.size() == 0 ? deque1 : deque2;        while(deque_pop.size() > 1) deque_push.add(deque_pop.pollLast());        return deque_pop.pollLast();    }}

4. 用一个数组实现两个栈

说明如何用一个数组A[1..n]来实现两个栈,使得两个栈中的元素总和不到n时,两个都不会发生上溯。注意PUSH和POP操作的时间应为O(1)
思路:两个栈从数组的前后开始向中间存储。

class Stack {    int[] arr;    int flag1 = -1, flag2  = -1;    public Stack(n){        arr = new int[n];        flag2 = n;    }    public void push1(int x) {        if(flag1 == (flag2 - 1)) return;        arr[++flag1] = x;     }    public void push2(int x) {        if(flag1 == (flag2 - 1)) return;        arr[--flag2] = x;     }    public int pop1() {        if(flag1 > -1) return arr[flag1--];     }    public int pop2() {        if(flag2 < n) return arr[flag2++];     }}

思考:用一个数组实现三个栈呢。
可以使用交叉索引,像上一题存两个栈的话,一个栈可以存储在0,2,4,6…/另一存储在1,3,5,7…
若三个栈就可以存储成0,3,6,9…./1,4,7,10…/2,5,8,11….
若还沿用上题方法,可以将第三个栈存储为:mid, mid+1, mid-1, mid+2, mid-2这样对称存储。


5. 栈对递归思想的考察

翻转栈中所有元素,要求额外空间复杂度o(1)
用递归来实现(与汉诺塔思想类似)
首先弹出栈顶元素top1,将剩余n-1栈递归反转,反转后弹出当前栈顶元素top2,再递归反转n-2栈。
放入top1元素,反转n-1栈。
最后放入top2元素。

public void reverseStack(Deque<Integer> deque){    if(deque.size() == 0) return;    int top1 = deque.pollLast();    reverseStack(deque);    if(deque.size() == 0) deque.add(top1);    else{        int top2 = deque.pollLast();        reverseStack(deque);        deque.add(top1);        reverseStack(deque);        deque.add(top2);    }}

-给栈中元素排序
类似冒泡排序的递归思想,每次将最小的值弹到栈顶,然后从下一个元素开始进行下轮的冒泡递归

public void sortStack(Deque<Integer> deque){    if(deque.size() == 0) return;    int top1 = deque.pollLast();    sortStack(deque);    if(deque.size() == 0) deque.add(top1);    else{        int top2 = deque.pollLast();        if(top1 <= top2) {            deque.add(top2);            deque.add(top1);        }        else{            deque.add(top1);            sortStack(deque);            deque.add(top2);        }    }}
0 0