
文章目录
- 一、栈
 - 
- 1.leetcode20.有效的括号
 - 
- 1.1.题目描述
 - 1.2.思路分析
 - 1.3.代码实现
 
 - 2.leetcode155.最小栈
 - 
- 2.1.题目描述
 - 2.2.思路分析
 - 2.3.代码实现
 
 
 - 二、队列
 - 
- 1.leetcode225.用队列实现栈
 - 
- 1.1.题目描述
 - 1.2.思路分析
 - 1.3.代码实现
 
 - 2.leetcode232.用栈实现队列
 - 
- 2.1题目描述
 - 2.2.思路分析
 - 2.3.代码实现
 
 
 
一、栈
1.leetcode20.有效的括号
1.1.题目描述

1.2.思路分析
找反例
 1.给定一个字符串,首先要把字符串转为字符数组一个个的判断
 2.找到不满足闭合条件的反例即可
 使用栈这个结构:
 1.转为字符数组一个个的判断
 2.碰到左括号就入栈
 3.碰到右括号就把栈顶的左括号出栈,与右括号比较,查看是否匹配,若匹配则继续向下判断,若不匹配则找到反例,返回false;当整个字符串走完,且栈为空,则说明字符串是符合条件的
1.3.代码实现
public boolean isValid(String s) {
        Stack<Character> stack = new Stack<>();
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (c == '(' || c == '[' || c == '{'){
                stack.push(c);
            }else{
                if (stack.isEmpty()){
                    return false;
                }
                char top = stack.pop();
                //找反例
                if (c == ')' && top != '('){
                    return false;
                }
                if (c == ']' && top != '['){
                    return false;
                }
                if (c == '}' && top != '{'){
                    return false;
                }
            }
        }
        return stack.isEmpty();
    }
2.leetcode155.最小栈
2.1.题目描述

2.2.思路分析
题目需要我们在栈的基础上拓展一个getMin方法,可以立即取得当前栈的最小值,时间复杂度为O(1),
 双栈思想:
 我们可以使用两个栈,s1和s2,s1保存实际元素,s2永远保存最小元素
 
 s1和s2同时入元素
 整个操作的核心在于
 当s2为空时,直接入栈
 当s2栈顶的元素 > 当前元素,也是直接入栈
 当s2栈顶的元素 < 当前元素,就把栈顶的元素在入一次栈(保证s2的元素个数和s1的元素个数保持一致);如果不一致,同步出栈后,s2为空了,s1还有元素,就无法判断了,元素个数相同,入栈和出栈操作都是同步的,那么s2的栈顶就永远保存了当前数据的最小元素。
 那么此时的s2的栈顶元素一定是最小元素,只用调用s2.peek();即可
2.3.代码实现
class MinStack {
    public MinStack() {
    }
    
   //s1永远保存实际元素
    private Stack<Integer> s1 = new Stack<>();
    //s2顶部永远保存最小元素
    private Stack<Integer> s2 = new Stack<>();
    
    public void push(int val) {
        s1.push(val);
        if (s2.isEmpty()){
            s2.push(val);
        }else{
            int peek = s2.peek();
            s2.push(Math.min(val,peek));
        }
    }
    public void pop() {
        s1.pop();
        s2.pop();
    }
    public int top() {
        return s1.peek();
    }
    public int getMin() {
        return s2.peek();
    }
}
/**
 * Your MinStack object will be instantiated and called as such:
 * MinStack obj = new MinStack();
 * obj.push(val);
 * obj.pop();
 * int param_3 = obj.top();
 * int param_4 = obj.getMin();
 */
二、队列
1.leetcode225.用队列实现栈
1.1.题目描述

1.2.思路分析
上一题采用了双栈思想,一个栈保存实际元素,另一个栈作为辅助作用,本题也可以采用相同的思路,其中一个队列q1永远都是实际存储元素的队列,栈的pop就是q1的poll,栈的peek就是q1的peek,栈的push就是q1的offer,保证q1和栈的操作保持一致
 另外一个队列q2作为辅助
 
 一定记住,q1永远是储存元素的队列,栈和队列的出队顺序刚好是相反的,先让新元素入q2,然后让q1的所有元素出队再入q2,然后我们只需要将q1和q2的引用交换一下即可,那么q1还是储存元素的队列
1.3.代码实现
class MyStack {
    public MyStack() {
    }
    
 //queue永远是实际保存元素的队列
    private Queue<Integer> queue1 = new LinkedList<>();
    //queue作为辅助
    private Queue<Integer> queue2 = new LinkedList<>();
    public void push(int x) {
        //新元素直接入队2
         queue2.offer(x);
        //将旧元素依次出队1,入队2
        while(!queue1.isEmpty()){
            queue2.offer(queue1.poll());
        }
        //交换queue1和queue2
        Queue<Integer> temp;
        temp = queue1;
        queue1 = queue2;
        queue2 = temp;
    }
    public int pop() {
        return queue1.poll();
    }
    public int top() {
        return queue1.peek();
    }
    public boolean empty() {
        return queue1.isEmpty();
    }
}
/**
 * Your MyStack object will be instantiated and called as such:
 * MyStack obj = new MyStack();
 * obj.push(x);
 * int param_2 = obj.pop();
 * int param_3 = obj.top();
 * boolean param_4 = obj.empty();
 */
2.leetcode232.用栈实现队列
2.1题目描述

2.2.思路分析
同样的思路,双栈思路
 
 s1永远是保存元素的栈
 1.先将s1中的元素依次弹出放入s2中
 2.将新元素放入s1中 – – > 此时这个元素就是s1的栈底(队尾元素)
 3.再将s2中的元素依次弹回到s1(此时s1就是先进先出的队列)
2.3.代码实现
class MyQueue {
    public MyQueue() {
    }
    
   //s1永远保存实际元素
    private Stack<Integer> s1 = new Stack<>();
    private Stack<Integer> s2 = new Stack<>();
    public void push(int x) {
        while(!s1.isEmpty()){
            s2.push(s1.pop());
        }
        s1.push(x);
        while (!s2.isEmpty()){
            s1.push(s2.pop());
        }
    }
    public int pop() {
        return s1.pop();
    }
    public int peek() {
        return s1.peek();
    }
    public boolean empty() {
        return s1.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();
 */
