夸父追日:第五章 栈与队列part01

今日收获:栈和队列的理论基础,用栈实现队列,用队列实现栈,栈的经典应用之消消乐

1. 栈-先进后出(Java)

(1)构造栈,以存储Integer类型为例,Stack类是泛型类

Stack<Integer> stack = new Stack<>();

Java中Stack类的源码: 底层可以用数组或链表实现

(2)常用方法

2. 队列-先进先出(Java)

(1)构造队列,以存储Integer为例,利用LinkedList实例化

Queue<Integer> queue=new LinkedList<>();

Java中的Queue是一个接口,LinkedList实现了这个接口

(2)常用方法:

3. 用栈实现队列

题目链接:232. - 力扣(LeetCode)

思路:需要用到两个栈,一个栈用来存储元素,另外一个栈用来弹出元素。弹出元素时,首先需要判断弹出栈是否为空,如果为空就将存储栈中的元素移入,不为空则优先弹出此栈中的元素。

方法:

class MyQueue {
    Stack<Integer> stackIn=new Stack<>();
    Stack<Integer> stackOut=new Stack<>();
    int size=0;

    public MyQueue() {
        
    }
    
    public void push(int x) {
        stackIn.push(x);
        size++;
    }
    
    public int pop() {
        if (stackOut.isEmpty()){
            while (!stackIn.isEmpty()){
                int temp=stackIn.pop();
                stackOut.push(temp);
            }
        }
        size--;
        return stackOut.pop();
    }
    
    public int peek() {
        if (stackOut.isEmpty()){
            while (!stackIn.isEmpty()){
                int temp=stackIn.pop();
                stackOut.push(temp);
            }
        }
        return stackOut.peek();
    }
    
    public boolean empty() {
        if (size==0){
            return true;
        }
        return false;
    }
}

/**
 * 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();
 */

总结:将栈中的元素弹出再进入另一个栈,此时另一个栈中的出栈顺序就和队列中相同了。

4. 用队列实现栈

题目链接:225. - 力扣(LeetCode)

思路:利用两个队列实现。添加元素时,首先将元素进入一个空队列1,原来存储元素的队列2全部清空,将元素转移到队列1中,然后队列1和队列2互换。

方法:

class MyStack {
    Queue<Integer> queue1; // 和栈中的元素顺序相等
    Queue<Integer> queue2;

    public MyStack() {
        queue1=new LinkedList<>();
        queue2=new LinkedList<>();
    }
    
    public void push(int x) {
        queue2.offer(x);
        while (!queue1.isEmpty()){
            queue2.offer(queue1.poll());
        }
        // 交换两个队列
        Queue<Integer> temp=new LinkedList<>();
        temp=queue1;
        queue1=queue2;
        queue2=temp;
    }
    
    public int pop() {
        return queue1.poll();
    }
    
    public int top() {
        return queue1.peek();
    }
    
    public boolean empty() {
        return queue1.size()==0?true:false;
    }
}

/**
 * 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();
 */

总结:队列1中的元素出队顺序和栈中相同。整体思路类似于汉诺塔:先用空的柱子存储新来的元素,然后将之前的元素转移到这个柱子上,最后交换两个柱子。

5. 栈的经典应用-消消乐

(1)有效括号

题目链接:20. - 力扣(LeetCode)

思路:创建一个栈,遍历字符串时遇到左括号则将相应的右括号压入栈中;遍历到右括号时首先判断栈是否为空,为空则不匹配(多余右括号),不为空则判断栈顶元素是否和当前遍历的右括号相等,不相等则说明括号不匹配;遍历结束后判断栈是否为空(不为空说明左括号多余)。注意字符串的长度必须是偶数,根据此条件剪枝。

方法:

class Solution {
    public boolean isValid(String s) {
        Stack<Character> stack=new Stack<>();

        if (s.length()%2!=0){
            return false;  // 剪枝情况
        }

        // 遇到左括号就压入与之对应的右括号,遇到右括号判断栈顶元素是否与之相同
        for (int i=0;i<s.length();i++){
            char c=s.charAt(i);
            if (c=='('){stack.push(')');}
            else if (c=='{'){stack.push('}');}
            else if (c=='['){stack.push(']');}
            else if (c==')'||c=='}'||c==']'){
                if (stack.isEmpty()||stack.pop()!=c){
                    return false;
                }
            }
        }

        if (!stack.isEmpty()){
            return false;
        }

        return true;
    }
}

总结:需要考虑三种不匹配的情况:右括号多余,括号不匹配,左括号多余。

(2)删除字符串中的重复相邻项

题目链接:1047. - 力扣(LeetCode)

思路:用栈存储遍历过的字符,除了第一个字符之外,其他字符都要和栈顶元素比较,如果相同就弹出栈顶元素,继续遍历下一个字符;否则将当前元素入栈。

方法:

class Solution {
    public String removeDuplicates(String s) {
        Stack<Character> stack=new Stack<>();

        for (int i=0;i<s.length();i++){
            char c=s.charAt(i);
            if (!stack.isEmpty() && stack.peek()==c){
                stack.pop();
                continue;
            }
            stack.push(c);
        }

        char[] result=new char[stack.size()];
        int k=stack.size()-1;
        while (!stack.isEmpty()){
            result[k--]=stack.pop();
        }
        return new String(result);
    }
}

总结:栈非常适合判断相邻元素或者匹配的情况,像开心消消乐一样,遇到符合条件的就消除,不符合条件就入栈积压

  • 13
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值