程式碼隨想錄演算法訓練營,9月6日 | 232.用棧實現佇列,225. 用佇列實現棧,20. 有效的括號,1047. 刪除字串中的所有相鄰重複項

漪欢酒發表於2024-09-07

棧與佇列理論基礎
1.佇列是先進先出,棧是先進後出
2.佇列:
主要操作:
offer(): 向佇列尾部新增元素。
poll(): 從佇列頭部移除並返回元素。
peek(): 檢視佇列頭部的元素但不移除。
實現: 在Java中可以使用 java.util.Queue 介面的實現類(如 LinkedList、PriorityQueue 和 ArrayDeque)來使用佇列。
3.棧:
主要操作:
push(): 將一個元素壓入棧頂。
pop(): 從棧頂彈出一個元素。
peek(): 檢視棧頂的元素但不彈出。
實現: 在Java中可以使用 java.util.Stack 類或使用 Deque 介面的實現(如 LinkedList、ArrayDeque)來模擬棧的行為。Stack 類比較老舊,不推薦使用,Deque 更靈活且高效。

232.用棧實現佇列
題目連結:232.用棧實現佇列
文件講解︰程式碼隨想錄(programmercarl.com)
影片講解︰用棧實現佇列
日期:2024-09-06

想法:新建兩個棧,入佇列直接push元素到stIn裡,出佇列,如果stOut為空,就先將stIn的元素全push進stOut,stOut出一個元素,不為空直接出,佇列為空,兩個棧為空。
Java程式碼如下:

class MyQueue {
    Stack<Integer> stIn;
    Stack<Integer> stOut;
    public MyQueue() {
        stIn = new Stack<>();
        stOut = new Stack<>();
    }
    
    public void push(int x) {
        stIn.push(x);
    }
    
    public int pop() {
        if(!stOut.isEmpty()) return stOut.pop();
        else{
            while(!stIn.empty()){
                stOut.push(stIn.pop());
            }
        }
        return stOut.pop();
    }
    
    public int peek() {
        if(!stOut.isEmpty()) return stOut.peek();
        else{
            while(!stIn.empty()){
                stOut.push(stIn.pop());
            }
        }
        return stOut.peek();
    }
    
    public boolean empty() {
        return stIn.isEmpty() && stOut.isEmpty();
    }
}

225. 用佇列實現棧
題目連結:225. 用佇列實現棧
文件講解︰程式碼隨想錄(programmercarl.com)
影片講解︰用佇列實現棧
日期:2024-09-06

想法:可以用一個佇列來實現,push操作就正常入,pop的話將佇列裡除最後一個的元素全部重新加到佇列,然後poll出的值就是pop的值了,top也是同樣想法,empty判一下空。
Java程式碼如下:

class MyStack {
    Queue<Integer> que;
    public MyStack() {
        que = new LinkedList<>();
    }
    
    public void push(int x) {
        que.offer(x);
    }
    
    public int pop() {
        rePosition();
        return que.poll();
    }
    
    public int top() {
        rePosition();
        int res = que.poll();
        que.offer(res);
        return res;
    }
    
    public boolean empty() {
        return que.isEmpty();
    }

    private void rePosition(){
        int size = que.size();
        size--;
        while (size-- > 0) {
            que.offer(que.poll());
        }
    }
}

總結:top的時候沒注意如果將佇列順序改了,再peek是不能實現只查不改的,這時要還原下佇列,將top的那個值再塞回佇列即可。

20. 有效的括號
題目連結:20. 有效的括號
文件講解︰程式碼隨想錄(programmercarl.com)
影片講解︰有效的括號
日期:2024-09-06

想法:匹配型別題考慮用棧,第一種情況:已經遍歷完了字串,但是棧不為空,說明有相應的左括號沒有右括號來匹配,所以return false
第二種情況:遍歷字串匹配的過程中,發現棧裡沒有要匹配的字元。所以return false
第三種情況:遍歷字串匹配的過程中,棧已經為空了,沒有匹配的字元了,說明右括號沒有找到對應的左括號return false
Java程式碼如下:

class Solution {
    public boolean isValid(String s) {
        Stack<Character> st = new Stack<>();
        char[] ch = s.toCharArray();
        for (int i = 0; i < s.length(); i++){
            if (ch[i] == '('){
                st.push(')');
            }else if (ch[i] == '['){
                st.push(']');
            }else if (ch[i] == '{'){
                st.push('}');
            }else if (st.isEmpty() || st.peek() != ch[i]){
                return false;
            }else {
                st.pop();
            }
        }
        return st.isEmpty();
    }
}

總結:要熟悉這種匹配模式的各種邊界判定。

1047. 刪除字串中的所有相鄰重複項
題目連結:1047. 刪除字串中的所有相鄰重複項
文件講解︰程式碼隨想錄(programmercarl.com)
影片講解︰刪除字串中的所有相鄰重複項
日期:2024-09-06

想法:用棧來存字串中的元素,棧頂遇到相同的就刪,剩下的元素如果是依次pop出就是倒序的,每一次將輸出的加在最前面即可
Java程式碼如下:

class Solution {
    public String removeDuplicates(String s) {
        ArrayDeque<Character> deque = new ArrayDeque<>();
        char c;
        for(int i = 0; i < s.length(); i++){
            c = s.charAt(i);
            if(deque.isEmpty() || deque.peek() != c){
                deque.push(c);
            }else{
                deque.pop();
            }
        }
        String str = "";
        while (!deque.isEmpty()) {
            str = deque.pop() + str;
        }
        return str;
    }
}

總結:Java中用ArrayDeque的情況較多,但也要注意跟LinkedList的區別,參考:https://stackoverflow.com/questions/6163166/why-is-arraydeque-better-than-linkedlist

相關文章