算法训练day11-栈与队列

232.用栈实现队列

题目

使用栈实现队列的下列操作:

push(x) -- 将一个元素放入队列的尾部。
pop() -- 从队列首部移除元素。
peek() -- 返回队列首部的元素。
empty() -- 返回队列是否为空。

思路

首先要理解栈和队列的基本特性,

栈的操作:先进后出

队列操作:先进先出

由此能够看出,栈和队列的操作顺序刚好相反,由此可以想到用两个栈组合起来实现队列的操作。

具体实现步骤:

1.定义两个栈stack1,stack2,并分别初始化

2.入队操作就直接使用stack1入栈操作,仅是为了存储数据

3.peek()出队操作,这里要考虑几种情况:

3.1.stack2为空,stack1不为空,此时出队操作需要先将stack1中的元素全部弹出到stack2,然后返回stack2的栈顶元素即可。

3.2.stack2不为空,直接返回stack2栈顶元素。

4.pop()操作,与peek相似,所以直接调用peek(),然后再直接弹出stack2()栈顶元素。

5.判空,当stack1和stack2都为空时,队列为空。

代码实现

class MyQueue {
    // stack1 入队栈,stack2 出队栈
    // 入队实现:stack1入栈
    // 出队实现:stack2出栈,如果为空则把stack1中的所有元素弹出压入stack2.
    // 如果stack1&&stack2都为空,则整个队列为空
    private Stack<Integer> stack1;
    private Stack<Integer> stack2;


    public MyQueue() {
       stack1 = new Stack<>();
       stack2 = new Stack<>();
    }
    
    public void push(int x) {
        stack1.push(x);
    }
    
    public int pop() {
        peek();
        return stack2.pop();
    }
    
    public int peek() {
        if(!stack1.empty()&&stack2.empty()){
            while(!stack1.empty()){
               stack2.push(stack1.pop());
            }
        }
        return stack2.peek();
    }
    
    public boolean empty() {
       if(stack1.empty()&&stack2.empty()){
           return true;
       }
       return false;
    }
}

225. 用队列实现栈

题目

使用队列实现栈的下列操作:

  • push(x) -- 元素 x 入栈
  • pop() -- 移除栈顶元素
  • top() -- 获取栈顶元素
  • empty() -- 返回栈是否为空

思路

解法一:双队列实现栈

用两个队列实现栈时,一个队列queue1用于存储,所有入栈都入queue1,另一个队列queue2用做备份。

入栈:直接存放进queue1,queue1.offer(x);

pop():1.获取queue1的元素数量记作size;

            2.将queue1全部出队并备份到queue2中;

             3.将queue2中的前size-1个元素出队并重新入队到queue1;

             4.queue2中仅剩的一个元素就是需要的栈顶元素,将其弹出queue2.pop()并返回;

peek(): 与pop()操作仅第四步不一样,将queue2中的最后一个元素弹出并重新入队到queue1中,然后返回。

empty(): 当queue1为空时,栈为空。

代码实现

class MyStack {
    private Queue<Integer> queue1;
    private Queue<Integer> queue2; 
 
    public MyStack() {
        queue1 = new LinkedList<>();
        queue2 = new LinkedList<>();
    }
    
    public void push(int x) {
        queue1.offer(x);
    }
    
    public int pop() {
       while(!queue1.isEmpty()){
          queue2.offer(queue1.poll());
       }
       int size = queue2.size();
       for(int i=1;i<size;i++){
           queue1.offer(queue2.poll());
       }
       int top = queue2.poll();
       return top;
    }
    
    public int top() {
       while(!queue1.isEmpty()){
          queue2.offer(queue1.poll());
       }
       int size = queue2.size();
       for(int i=1;i<size;i++){
           queue1.offer(queue2.poll());
       }
       int top = queue2.poll();
       queue1.offer(top);
       return top;
    }
    
    public boolean empty() {
       if(queue1.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--;
        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. 有效的括号

给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。

有效字符串需满足:

  • 左括号必须用相同类型的右括号闭合。
  • 左括号必须以正确的顺序闭合。
  • 注意空字符串可被认为是有效字符串。

示例 1:

  • 输入: "()"
  • 输出: true

思路

因为有效的字符括号都是成对的而且对称匹配,这种规律很适合使用栈来解决。

具体实现步骤:

首先定义一个栈,从左到右遍历字符串,遇到左括号压入栈。

遇到右括号,弹出栈顶元素判断是否是对应的左括号,如果不是返回false.

特殊情况处理:

1.如果只有左括号的情况,必然最后栈不为空,判断栈不为空就返回false.

2.如果只有右括号的情况,必然栈一直为空,在遇到右括号时,判断栈为空就返回false.

代码实现

class Solution {
    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);
          }
          if(c==')'){
              if(stack.empty()){
                  return false;
              }
              char top = stack.pop();
              if(top!='('){
                  return false;
              }
          }
          if(c=='}'){
              if(stack.empty()){
                  return false;
              }
              char top = stack.pop();
              if(top!='{'){
                  return false;
              }
          }
          if(c==']'){
              if(stack.empty()){
                  return false;
              }
              char top = stack.pop();
              if(top!='['){
                  return false;
              }
          }          
      }
      if(!stack.empty()){
        return false;
      }
      return true;
    }
}

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

给出由小写字母组成的字符串 S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。

在 S 上反复执行重复项删除操作,直到无法继续删除。

在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。

示例:

  • 输入:"abbaca"
  • 输出:"ca"
  • 解释:例如,在 "abbaca" 中,我们可以删除 "bb" 由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。之后我们得到字符串 "aaca",其中又只有 "aa" 可以执行重复项删除操作,所以最后的字符串为 "ca"。

思路

与括号匹配类似的解法,都可以利用栈的特性来解决。

代码实现

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.empty()){
              stack.push(c);
          } else{
          char  top =  stack.peek();
          if(top==c){
             stack.pop();
           }else{
              stack.push(c);
           }
          }
      }
      String str = "";
      while(!stack.empty()){
        char  c = stack.pop();
        str = c+str;
      }
      return  str;
    }
}
class Solution {
    public String removeDuplicates(String S) {
        //ArrayDeque会比LinkedList在除了删除元素这一点外会快一点
        //参考:https://stackoverflow.com/questions/6163166/why-is-arraydeque-better-than-linkedlist
        ArrayDeque<Character> deque = new ArrayDeque<>();
        char ch;
        for (int i = 0; i < S.length(); i++) {
            ch = S.charAt(i);
            if (deque.isEmpty() || deque.peek() != ch) {
                deque.push(ch);
            } else {
                deque.pop();
            }
        }
        String str = "";
        //剩余的元素即为不重复的元素
        while (!deque.isEmpty()) {
            str = deque.pop() + str;
        }
        return str;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值