<Java>手把手带你刷leetcode(栈和队列篇)

2年前 (2022) 程序员胖胖胖虎阿
243 0 0

<Java>手把手带你刷leetcode(栈和队列篇)


文章目录

  • 一、栈
    • 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.题目描述

<Java>手把手带你刷leetcode(栈和队列篇)

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.题目描述

<Java>手把手带你刷leetcode(栈和队列篇)

2.2.思路分析

题目需要我们在栈的基础上拓展一个getMin方法,可以立即取得当前栈的最小值,时间复杂度为O(1),
双栈思想:
我们可以使用两个栈,s1和s2,s1保存实际元素,s2永远保存最小元素
<Java>手把手带你刷leetcode(栈和队列篇)
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.题目描述

<Java>手把手带你刷leetcode(栈和队列篇)

1.2.思路分析

上一题采用了双栈思想,一个栈保存实际元素,另一个栈作为辅助作用,本题也可以采用相同的思路,其中一个队列q1永远都是实际存储元素的队列,栈的pop就是q1的poll,栈的peek就是q1的peek,栈的push就是q1的offer,保证q1和栈的操作保持一致
另外一个队列q2作为辅助
<Java>手把手带你刷leetcode(栈和队列篇)
一定记住,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题目描述

<Java>手把手带你刷leetcode(栈和队列篇)

2.2.思路分析

同样的思路,双栈思路
<Java>手把手带你刷leetcode(栈和队列篇)
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();
 */

版权声明:程序员胖胖胖虎阿 发表于 2022年11月5日 下午12:32。
转载请注明:<Java>手把手带你刷leetcode(栈和队列篇) | 胖虎的工具箱-编程导航

相关文章

暂无评论

暂无评论...