Leetcode 题解 - 栈和队列

150 阅读2分钟

1. 用栈实现队列

Leetcode (opens new window)/ 力扣

栈的顺序为后进先出,而队列的顺序为先进先出。使用两个栈实现队列,一个元素需要经过两个栈才能出队列,在经过第一个栈时元素顺序被反转,经过第二个栈时再次被反转,此时就是先进先出顺序。

/**
 * 思路:维护两个栈,一个栈负责输入,一个栈负责输出
 * push() 直接将数压入输入栈即可
 * pop() 首先检查输出栈是否为空,如果为空就就把输入栈
 * 的数读出到输出栈中
 * peek() 
 * 
 */
class MyQueue {
    
    private Stack<Integer> in;
    private Stack<Integer> out;

    public MyQueue() {
        in = new Stack<>();
        out = new Stack<>();
    }
    
    public void push(int x) {
        in.push(x);
    }
    
    public int pop() {
        if (out.isEmpty()) {
            inToOut();
        }

        return out.pop();
    }
    
    public int peek() {
        inToOut();
        return out.peek();
    }
    
    public boolean empty() {
        return in.isEmpty() && out.isEmpty(); 
    }

    public void inToOut() {
        if (out.isEmpty()) {
            while (!in.isEmpty()) {
                out.push(in.pop());
            }
        }
    }
}


2. 用队列实现栈

Leetcode (opens new window)/ 力扣

在将一个元素 x 插入队列时,为了维护原来的后进先出顺序,需要让 x 插入队列首部。而队列的默认插入顺序是队列尾部,因此在将 x 插入队列尾部之后,需要让除了 x 之外的所有元素出队列,再入队列。

class MyStack {
    Queue<Integer> queue;

    public MyStack() {
        queue = new LinkedList<>();
    }
    
    public void push(int x) {
        queue.add(x);

        int size = queue.size();

        while (size-- > 1) {
            queue.add(queue.poll());
        }
    }
    
    public int pop() {
        return queue.poll();
    }
    
    public int top() {
        return queue.peek();
    }
    
    public boolean empty() {
        return queue.isEmpty();
    }
}


3. 最小值栈

Leetcode (opens new window)/ 力扣

class MinStack {
    // 数据栈
    private Stack<Integer> stack;
    // 最小值栈,与数据栈对应
    private Stack<Integer> minStack;

    public MinStack() {
        stack = new Stack<>();
        minStack = new Stack<>();
    }
    
    public void push(int val) {
        stack.push(val);

        // 如果为空,就不用比较,直接入栈
        if (minStack.isEmpty()) {
            minStack.push(val);
        } else {
            // 如果栈顶元素比 val 小,直接入栈
            if (minStack.peek() > val) {
                minStack.push(val);
            // 否则将以前的最小值入栈    
            } else {
                minStack.push(minStack.peek());
            }
        }
    }
    
    public void pop() {
        // 两个栈是同步的
        stack.pop();
        minStack.pop();
    }
    
    public int top() {
        return stack.peek();
    }
    
    public int getMin() {
        return minStack.peek();
    }
}


4. 用栈实现括号匹配

Leetcode (opens new window)/ 力扣

class Solution {
    public boolean isValid(String s) {
        if (s.length() % 2 == 1) {
            return false;
        }
        Stack<Character> stack = new Stack<>();

        for (int i = 0; i < s.length(); i++) {
            char ch = s.charAt(i);
            if (ch == '(' || ch == '{' || ch == '[') {
                stack.push(ch);
            } else {
                if (stack.isEmpty()) {
                    return false;
                }
                char temp = stack.pop();
                boolean b1 = (ch == ')' && temp != '(');
                boolean b2 = (ch == '}' && temp != '{');
                boolean b3 = (ch == ']' && temp != '[');

                if (b1 || b2 || b3) {
                    return false;
                }
            }
        }

        return stack.isEmpty();
    }
}


5. 每日温度

Leetcode (opens new window)/ 力扣

(1)直接暴力遍历

class Solution {
    public int[] dailyTemperatures(int[] temperatures) {
        int[] result = new int[temperatures.length];
        
        for (int i = 0; i < temperatures.length; i++) {
            int count = 0;
            // 用于计数,如果真的有比今天温度高的就与 count 相加
            int flag = 0;

            for (int j = i + 1; j < temperatures.length; j++) {
                if (temperatures[i] < temperatures[j]) {
                    count += flag + 1;
                    break;
                }
                flag++;
            }

            result[i] = count;
        }

        return result;
    }
}

(2)单调栈

class Solution {
    public int[] dailyTemperatures(int[] temperatures) {
        int[] result = new int[temperatures.length];
        Stack<Integer> stack = new Stack<>();
        
        for (int i = 0; i < temperatures.length; i++) {
            while (!stack.isEmpty() && temperatures[i] > temperatures[stack.peek()]) {
                int index = stack.pop();
                result[index] = i - index;
            }

            stack.push(i);
        }

        return result;
    }
}


6. 下一个更大元素 II *

Leetcode (opens new window)/ 力扣

class Solution {
    public int[] nextGreaterElements(int[] nums) {
        int length = nums.length;
        int[] result = new int[length];
        Stack<Integer> stack = new Stack<>();
        // 把数组初始化为 -1
        Arrays.fill(result, -1);

        for (int i = 0; i < length * 2; i++) {
            int temp = nums[i % length];

            while (!stack.isEmpty() && temp > nums[stack.peek()]) {
                result[stack.pop()] = temp;
            }

            if (i < length) {
                stack.push(i);
            }
        }

        return result;
    }
}