算法训练营day09 | 栈与队列 part01

49 阅读2分钟

理论基础

  • stack 栈 FILO
    • push,pop
  • queue 队列 FIFO
    • enqueue,dequeue

232.用栈实现队列

题目 文章

class MyQueue {
    Stack<Integer> main;
    Stack<Integer> second;
    public MyQueue() {
        main = new Stack<Integer>();
        second = new Stack<Integer>();
    }
    
    public void push(int x) {
        main.push(x);
    }
    
    public int pop() {
        dumpMainSecond();
        return second.pop();
    }
    
    public int peek() {
        dumpMainSecond();
        return second.peek();
    }
    
    public boolean empty() {
        return main.isEmpty() && second.isEmpty();
    }

    private void dumpMainSecond(){
        if(!second.isEmpty()){
            return;
        }

        while(!main.isEmpty()){
            second.push(main.pop());
        }
    }
}

225. 用队列实现栈

题目 文章

class MyStack {

    Queue<Integer> main;
    Queue<Integer> second;
    public MyStack() {
        main = new LinkedList<>();
        second = new LinkedList<>();;
    }
    
    public void push(int x) {
        second.offer(x); // 先放在辅助队列中
        while (!main.isEmpty()){
            second.offer(main.poll());
        }
        Queue<Integer> queueTemp;
        queueTemp = main;
        main = second;
        second = queueTemp;
    }
    
    public int pop() {
        return main.poll();
    }
    
    public int top() {
        return main.peek();
    }
    
    public boolean empty() {
        return main.isEmpty();
    }
}

20. 有效的括号

题目 文章

class Solution {
    public boolean isValid(String s) {
        Stack<Character> stack = new Stack<>();
        char[] c = s.toCharArray();

        for(int i=0;i < c.length;i++){
            if(c[i] == '(' || c[i] == '{' || c[i] == '['){
                stack.push(c[i]);
            }else{
                if(stack.isEmpty()){return false;}
                char check = stack.pop();
                if(c[i] == ')' && check == '('){
                    continue;
                }else if(c[i] == '}' && check == '{'){
                    continue;
                }else if(c[i] == ']' && check == '['){
                    continue;
                }else{
                    return false;
                }
            }
        }

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

第一种情况:已经遍历完了字符串,但是栈不为空,说明有相应的左括号没有右括号来匹配,所以return false

第二种情况:遍历字符串匹配的过程中,发现栈里没有要匹配的字符。所以return false

第三种情况:遍历字符串匹配的过程中,栈已经为空了,没有匹配的字符了,说明右括号没有找到对应的左括号return false

那么什么时候说明左括号和右括号全都匹配了呢,就是字符串遍历完之后,栈是空的,就说明全都匹配了。

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

题目 文章


class Solution {
    public String removeDuplicates(String s) {
        Stack<Character> stack = new Stack<>();
        char[] c = s.toCharArray();
        for(int i=0;i < c.length;i++){
            if(stack.isEmpty()){
                stack.push(c[i]);
            }else{
                char p = stack.pop();
                if(c[i] != p){
                    stack.push(p);
                    stack.push(c[i]);
                }
            }
        }

        String res = "";
        while(!stack.isEmpty()){
            res = stack.pop() + res;
        }
        return res;
    
    }
}

随想录代码

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;
    }
}
  • 拿字符串直接作为栈,省去了栈还要转为字符串的操作。
class Solution {
    public String removeDuplicates(String s) {
        // 将 res 当做栈
        // 也可以用 StringBuilder 来修改字符串,速度更快
        // StringBuilder res = new StringBuilder();
        StringBuffer res = new StringBuffer();
        // top为 res 的长度
        int top = -1;
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            // 当 top > 0,即栈中有字符时,当前字符如果和栈中字符相等,弹出栈顶字符,同时 top--
            if (top >= 0 && res.charAt(top) == c) {
                res.deleteCharAt(top);
                top--;
            // 否则,将该字符 入栈,同时top++
            } else {
                res.append(c);
                top++;
            }
        }
        return res.toString();
    }
}
  • 双指针
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);
    }
}