06-栈与队列类


题目

232. 用栈实现队列

[请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):
实现 MyQueue 类:

  • void push(int x) 将元素 x 推到队列的末尾
  • int pop() 从队列的开头移除并返回元素
  • int peek() 返回队列开头的元素
  • boolean empty() 如果队列为空,返回 true ;否则,返回 false
    说明:
    你 只能 使用标准的栈操作 —— 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。
    你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。](https://leetcode.cn/problems/implement-queue-using-stacks/)

在这里插入图片描述
此题自己琢磨了1个小时,差不多能做出来,大体思路就是:

  1. push方法:直接就往st1里放数就好了
  2. pop方法:
    如果st2里面有元素,就弹出
    如果没有,然后将st1所有元素弹出,并放入st2中,然后弹出
  3. peak方法:
    就是利用上述的pop方法弹出,并记录数值,然后将数值再输入到st2上,返回x即可
  4. empty方法:
    就是判断st1和st2都为空,则返回true,否则返回false
class MyQueue {
    Stack<Integer> st1;
    Stack<Integer> st2;

    public MyQueue() {
        st1 = new Stack<Integer>();
        st2 = new Stack<Integer>();

    }
    
    public void push(int x) {
        st1.push(x);
    }
    
    public int pop() {
        if(!st2.isEmpty()){
           return st2.pop();
        }
        while(!st1.isEmpty()){
            st2.push(st1.pop());
        }
        return st2.pop();
    }
    
    public int peek() {
         int x = this.pop();
         st2.push(x);
         return x;
    }
    
    public boolean empty() {
        if(st1.isEmpty()&&st2.isEmpty()){
            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();
 */

学习:一定要懂得复用,功能相近的函数要抽象出来,不要大量的复制粘贴,很容易出问题!
在pop的时候,操作就复杂一些,输出栈如果为空,就把进栈数据全部导入进来(注意是全部导入),再从出栈弹出数据,如果输出栈不为空,则直接从出栈弹出数据就可以

不进行数据的全部导入,会导致不进行先进先出,若st1多个元素,导致st1栈的元素,顺序错乱

peak方法:然先用pop方法弹出,并记录为x,然后再push进去,返回x,此方法挺精彩,以前没见过

225. 用队列实现栈

请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。
实现 MyStack 类:

  • void push(int x) 将元素 x 压入栈顶。
  • int pop() 移除并返回栈顶元素。
  • int top() 返回栈顶元素。
  • boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。
    注意:
    你只能使用队列的基本操作 —— 也就是 push to back、peek/pop from front、size 和 is empty 这些操作。
    你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可
    在这里插入图片描述
    此题虽然没做过,但是由于上一题与此类似,基本上画个图,研究研究也能做出来,大约30分钟做左右,大体思路是:
  1. push方法:直接放进队列就好了
  2. pop方法,把1个元素放到队列1,其他元素放到队列2,然后把队列1与队列2进行调换,弹出队列2即可
  3. empty方法,和上题是一样的,若两队列皆为空,则返回true,否则则返回false
  4. top方法可以用上题方法类似的做法,先把元素退出队列,然后赋值,然后把元素再放回去

遇到的问题是:队列要实现的是Queue接口,而不是List接口,或者是其他的类,否则会导致很多方法无法调用
队列1与队列2进行交换需要新建一个队列,与字符串做交换是类似的

class MyStack {
    Queue<Integer> li1;      //  Queue而不是list
    Queue<Integer> li2;

    public MyStack() {
        li1 = new LinkedList<Integer>();
        li2 = new LinkedList<Integer>();
    }
    
    public void push(int x) {
        li1.add(x);
    }
    
    public int pop() {
        while(li1.size()!=1){           
            li2.add(li1.poll());
        }
        Queue<Integer> temp = new LinkedList<Integer>();
        temp = li1;
        li1 = li2;
        li2 = temp;
        return li2.poll();
      
    }
    
    public int top() {
        int x = this.pop();
        li1.add(x);
        return x;

    }
    
    public boolean empty() {
        if(li1.isEmpty()&&li2.isEmpty()){
            return true;
        }
        return false;

    }
}

学习:
两个队列实现栈:第二个队列实际上只是有备份的作用
第一队列实现栈:一个队列在模拟栈弹出元素的时候只要将队列头部的元素(除了最后一个元素外) 重新添加到队列尾部,此时在去弹出元素就是栈的顺序了。

class MyStack {
    // Deque 接口继承了 Queue 接口
    // 所以 Queue 中的 add、poll、peek等效于 Deque 中的 addLast、pollFirst、peekFirst
    Deque<Integer> que1;
    /** Initialize your data structure here. */
    public MyStack() {
        que1 = new ArrayDeque<>();
    }
    
    /** Push element x onto stack. */
    public void push(int x) {
        que1.addLast(x);
    }
    
    /** Removes the element on top of the stack and returns that element. */
    public int pop() {
        int size = que1.size();
        size--;
        // 将 que1 导入 que2 ,但留下最后一个值
        while (size-- > 0) {
            que1.addLast(que1.peekFirst());
            que1.pollFirst();
        }

        int res = que1.pollFirst();
        return res;
    }
    
    /** Get the top element. */
    public int top() {
        return que1.peekLast();
    }
    
    /** Returns whether the stack is empty. */
    public boolean empty() {
        return que1.isEmpty();
    }
}

20. 有效的括号

给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
在这里插入图片描述
此题看了十分钟,没有思路去做,应该思路比较简单才对~~~~

class Solution {
    public boolean isValid(String s) {
        Stack<Character> st = new Stack<>();
        char ch;
        for(int i=0;i<s.length();i++){
            ch=s.charAt(i);
            // 碰到左括号,就把相应的右括号入栈
            if(ch=='('){
                st.push(')');
            }else if(ch=='{'){
                st.push('}');
            }else if(ch == '['){
                st.push(']');
            }else if(st.isEmpty()||st.peek()!=ch){ //  1    2
                return false;
            }else{// 如果是右括号判断是和栈顶元素匹配
                st.pop();
            }
        }
        return st.isEmpty();   // 最后判断栈中元素是否匹配     //   3
    }
}

学习:
括号匹配是使用栈解决的经典为题
linux系统 cd命令也有用到栈

括号不匹配的三种情况?
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
此题实际上还是挺难的,需要考虑完三种不对的情况,然后如果匹配的话,还要对应栈中元素的弹出

1047. 删除字符串中的所有相邻重复项

给出由小写字母组成的字符串 S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。
在 S 上反复执行重复项删除操作,直到无法继续删除。
在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。

在这里插入图片描述此题和上一题差不多,差不多20分钟就做出来了,主要的思路就是:
先判空,然后如果栈中无元素或者元素不等于栈顶元素,则将元素放进栈中否则,则将弹出一个栈顶的元素
最后结束后,将栈中的元素弹出,加到sb中,对sb反转,然后转为String,并返回

碰到最大的问题是怎样才能把栈中的元素弹出并转为字符串,并且不会顺序错误,并且不会出现数组
解决方式就是转为sb,然后反转,最后转为String

class Solution {
    public String removeDuplicates(String s) {
        if(s.length()==0&&s==null) return null;
        Stack<Character> st = new Stack<Character>();
        char ch;
        for(int i=0;i<s.length();i++){
            ch = s.charAt(i);
            if(st.empty()||st.peek()!=ch){
                st.push(ch);
            }else{
                st.pop();
            }
        }
       StringBuilder sb = new StringBuilder();
       while(!st.empty()){
           sb.append(st.pop());
       }
       return sb.reverse().toString();
    }
}

150. 逆波兰表达式求值[中等]

239. 滑动窗口最大值【困难】

347. 前 K 个高频元素 【中等】

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值