棧與佇列理論基礎
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