代码随想录算法训练营第11天|232.用栈实现队列,225. 用队列实现栈,20. 有效的括号,1047. 删除字符串中的所有相邻重复项

一. 栈与队列

二. 栈与队列相关算法题

232.用栈实现队列

思路

  • 使用双栈一个负责输入一个负责输出
  • 输出栈由输入栈导入
  • 将导入的逻辑放在pop中只有输出栈为空时才需要导入
class MyQueue {

    Stack<Integer> in;
    Stack<Integer> out;

    public MyQueue() {
        in = new Stack<>();
        out = new Stack<>();
    }
    
    public void push(int x) {
        in.push(x);
    }
    
    public int pop() {
        //如果输出栈为空才需要从输入栈导入护据
        if (out.isEmpty()){
            while (!in.isEmpty()){  //每次导入都一次性全部导入到输出栈
                out.push(in.pop());
            }
        }
        return out.pop();
    }
    
    public int peek() {
        int result = this.pop();  //直接调用当前对象的pop()
        out.push(result); //将弹出的数据再压回去
        return result;
    }
    
    public boolean empty() {
        return in.empty() && out.empty();
    }
}

225.用队列实现栈

双队列实现

思路
  • 每次添加元素时都先放在辅组队列中
  • 然后将原队列中的元素追加到辅助队列中
  • 最后将辅助队列赋值给原队列,这样新添加的元素就在原队列的头
class MyStack {

    Queue<Integer> queue1; // 和栈中保持一样元素的队列
    Queue<Integer> queue2; // 辅助队列

    /**
     * Initialize your data structure here.
     */
    public MyStack() {
        queue1 = new LinkedList<>();
        queue2 = new LinkedList<>();
    }

    /**
     * Push element x onto stack.
     */
    public void push(int x) {
        queue2.offer(x); // 先放在辅助队列中
        while (!queue1.isEmpty()) {
            queue2.offer(queue1.poll());
        }
        Queue<Integer> queueTemp;
        queueTemp = queue1;
        queue1 = queue2;
        queue2 = queueTemp; // 最后交换queue1和queue2,将元素都放到queue1中
    }

    /**
     * Removes the element on top of the stack and returns that element.
     */
    public int pop() {
        return queue1.poll(); // 因为queue1中的元素和栈中的保持一致,所以这个和下面两个的操作只看queue1即可
    }

    /**
     * Get the top element.
     */
    public int top() {
        return queue1.peek();
    }

    /**
     * Returns whether the stack is empty.
     */
    public boolean empty() {
        return queue1.isEmpty();
    }
}

用一个队列实现

思路
  • 每次弹栈把队列中的所有元素都移到队列末尾除了最后一个元素
class MyStack {

    Queue<Integer> queue1;

    /**
     * Initialize your data structure here.
     */
    public MyStack() {
        queue1 = new LinkedList<>();
    }

    /**
     * Push element x onto stack.
     */
    public void push(int x) {
        queue1.offer(x);

    }

    /**
     * Removes the element on top of the stack and returns that element.
     */
    public int pop() {
        int size = queue1.size()-1; //因为要保留最后一个所以先提前减一
        while (size-- >0) {
            queue1.offer(queue1.poll());
        }
        return queue1.poll();
    }

    /**
     * Get the top element.
     */
    public int top() {
        int result = this.pop();
        queue1.offer(result);
        return result;
    }

    /**
     * Returns whether the stack is empty.
     */
    public boolean empty() {
        return queue1.isEmpty();
    }
}

20.有效的括号

思路
  • 首先要明确不匹配场景
    • 第一种情况,字符串里左方向的括号多余了 ,所以不匹配。
    • 第二种情况,括号没有多余,但是 括号的类型没有匹配上。
    • 第三种情况,字符串里右方向的括号多余了,所以不匹配
class Solution {
    public boolean isValid(String s) {
        if (s.length()%2!=0) return false; //长度为奇数不可能有效
        Stack<Character> stack = new Stack<>();
        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) == '('){
                stack.push(')');
            }else if (s.charAt(i) == '{') {
                stack.push('}');
            } else if (s.charAt(i) == '['){
                stack.push(']');
            } else if (stack.isEmpty() || s.charAt(i) != stack.peek()){
                return false; //1.栈为空证明有多余的右括号;2.当前栈顶右括号不等于当前第i位右括号
            } else {
                stack.pop(); //当前字符与栈顶元素相等弹栈判断下个右括号
            }
        }
        return stack.isEmpty(); //如果不为空证明字符串遍历完毕仍有没有匹配的左括号
    }
}

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

栈实现

思路
  • 使用栈存储最终元素,出现重复的弹出栈顶元素
class Solution {
    public String removeDuplicates(String s) {
        Stack<Character> stack = new Stack<>();
        for (int i = 0; i < s.length(); i++) {
            if (stack.isEmpty() || s.charAt(i) != stack.peek()){
                stack.push(s.charAt(i));
            }else {
                stack.pop();
            }
        }
        StringBuilder stringBuilder = new StringBuilder();
        stack.stream().forEach(character -> stringBuilder.append(character));
        return stringBuilder.toString();
    }
}

字符串实现

  • 字符串替换栈
class Solution {
    public String removeDuplicates(String s) {
        StringBuilder res = new StringBuilder();
        for (int i = 0; i < s.length(); i++) {
            if (res.length() == 0 || s.charAt(i) != res.charAt(res.length()-1)){
                res.append(s.charAt(i));
            }else {
                res.deleteCharAt(res.length()-1);
            }
        }
        return res.toString();
    }
}

双指针

思路
  • 定义快慢指针,直接用fast指针覆盖slow指针的值
  • 遇到前后相同值的,就跳过,即slow指针后退一步,下次循环就可以直接被覆盖掉了
class Solution {
    public String removeDuplicates(String s) {
        char[] ch = s.toCharArray();
        int fast = 0;
        int slow = 0;
        while(fast < s.length()){
            // 直接用fast指针覆盖slow指针的值
            ch[slow] = ch[fast];
            // 遇到前后相同值的,就跳过,即slow指针后退一步,下次循环就可以直接被覆盖掉了
            if(slow > 0 && ch[slow] == ch[slow - 1]){
                slow--;
            }else{
                slow++;
            }
            fast++;
        }
        return new String(ch,0,slow);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值