# 0-19 queue 與 stack 講義不是我寫的,網址在此 https://emanlaicepsa.github.io/2020/10/21/0-index/ 我只是將自己寫的練習題程式碼記錄下來。 最後更新日期:2024年10月7日 ## [ZeroJudge: e155. 10935 - Throwing cards away I](https://zerojudge.tw/ShowProblem?problemid=e155) ### Python 程式碼 執行時間最久約為 19 ms,使用記憶體最多約為 3.3 MB,通過測試。但是這樣寫效率不好,因為移除串列索引值 0 的資料時,需要將之後的資料記憶體位址都往前移一格,時間複雜度是 $O(n)$。 ```python= while True: n = int(input()) if n == 0: break elif n == 1: print("Discarded cards: ") print("Remaining card: 1") else: cards = [i for i in range(1, n+1)] discards = [] while len(cards) > 1: discards.append(cards.pop(0)) c = cards.pop(0) cards.append(c) print("Discarded cards: ", end="") for i in range(len(discards)): print("{:d}".format(discards[i]), end="\n" if i == len(discards)-1 else ", ") print("Remaining card: {:d}".format(cards[0])) ``` 執行時間最久約為 22 ms,使用記憶體最多約為 3.2 MB,通過測試。 ```python= from collections import deque while True: n = int(input()) if n == 0: break elif n == 1: print("Discarded cards: ") print("Remaining card: 1") else: cards = deque([i for i in range(1, n+1)]) discards = deque() while len(cards) > 1: discards.append(cards.popleft()) c = cards.popleft() cards.append(c) print("Discarded cards: ", end="") for i in range(len(discards)): print(f"{discards[i]:d}", end="\n" if i == len(discards)-1 else ", ") print(f"Remaining card: {cards[0]:d}") ``` ### C++ 程式碼 執行時間最久約為 2 ms,使用記憶體最多約為 316 kB,通過測試。 ```cpp= #include <iostream> #include <queue> using namespace std; int main() { int n; while(true) { cin >> n; if (n == 0) { break; } else if (n == 1) { cout << "Discarded cards: \n"; cout << "Remaining card: 1\n"; } else { queue<int> cards, discards; for(int i=1; i<=n; i++) cards.push(i); while(cards.size() > 1) { int d = cards.front(); cards.pop(); discards.push(d); int c = cards.front(); cards.pop(); cards.push(c); } cout << "Discarded cards: "; while(discards.size() > 1) { cout << discards.front() << ", "; discards.pop(); } cout << discards.front() << "\n"; cout << "Remaining card: " << cards.front() << "\n"; } } return 0; } ``` ## [ZeroJudge: c123. 00514 - Rails](https://zerojudge.tw/ShowProblem?problemid=c123) 後來我再一次寫到這題,看起來第二次的寫法比較精簡,[連結在這裡](https://hackmd.io/@yizhewang/rkRkKNzMJx#ZeroJudge-c123-00514---Rails)。 ### Python 程式碼 執行時間最久約為 0.2 s,使用記憶體最多約為 3.8 MB,通過測試。 ```python= import sys for line in sys.stdin: # 由標準輸入逐行讀取資料並存入字串 line N = int(line) # 將 line 轉成 int 並存入 N if N == 0: break # 如果 N 為 0 中止迴圈 else: # 如果 N 不為 0,讀取列車於 B 的排序 for line in sys.stdin: # 由標準輸入逐行讀取資料並存入字串 line if line == "0\n": # 如果 line 為 0\n,印出空行並跳出內層的 for 迴圈 print(); break; else: # 如果 line 不為 0\n A = [i for i in range(1, N+1)] # 産生列車於 A 的排序,由 1 ~ N B = list(map(int, line.split())) # 將 line 轉成串列 B,為列車於 B 的排序 station = [] # 暫時停在車站的車廂編號 flag = True # 是否可以達成題目要求的 B 排序,預設為 True for i in range(N): # 依序由 B 讀取要檢查的車廂編號並存入 need need = B[i] if station and station[-1] == need: # 如果 station 中有資料且最後一個車廂是要檢查的編號 station.pop(); continue # 將這個車廂移出 station,忽略 else 的部分,回到第17行繼續檢查 B 的下一個車廂 else: # 如果在 station 中沒有找到 need,改在 A 中尋找 need find = False # 是否在 A 當中找到 need,預設為 False while A: # 如果 A 還有資料則繼續執行 while 迴圈 a = A.pop(0) # 取出 A 最前方的資料並存入 a if a == need: # 如果 a 等於 need,找到了,find 設定為 True,跳出第23行的 while 迴圈 find = True; break else: # 如果 a 不等於 need,將 a 加入 station 最後面,繼續檢查 A 的下一個車廂 station.append(a) if not find: # 如果沒有在 A 找到 need,無法達成題目要求的排序 B,flag 設定為 False,跳出第17行的 for 迴圈 flag = False; break print("Yes" if flag else "No") # 如果 flag 為 True 印出 Yes,反之印出 No ``` ### C++ 程式碼 執行時間最久約為 80 ms,使用記憶體最多約為 336 kB,通過測試。 ```cpp= #include <iostream> #include <deque> using namespace std; int main() { int N; // 儲存資料的變數 N while(cin >> N) { // 由標準輸入讀取資料並存入 N if (N == 0) { // 如果 N 為 0 中止迴圈 break; } else { // 如果 N 不為 0,讀取列車於 B 的排序 while(true) { // 無窮迴圈 int d; cin >> d; // 由標準輸入讀取資料並存入 d if (d == 0) { // 如果 d 為 0,印出空行並跳出第13行的 while 迴圈 cout << "\n"; break; } else { // 如果 d 不為 0 deque<int> A, station; // 儲存資料用的雙向佇列 A 及 station for(int i=1; i<=N; i++) A.push_back(i); // 産生列車於 A 的排序,由 1 ~ N int B[N]; B[0] = d; // 列車於 B 的排序,記得要先存入 d for(int i=1; i<N; i++) { // 存入 B[1] ~ B[N-1] 的資料 cin >> d; B[i] = d; } bool flag = true; // 是否可以達成題目要求的 B 排序,預設為 true for(int i=0; i<N; i++) { // 依序由 B 讀取要檢查的車廂編號並存入 need int need = B[i]; if (!station.empty() && station.back() == need) { // 如果 station 中有資料且最後一個車廂是要檢查的編號 station.pop_back(); continue; // 將這個車廂移出 station,忽略 else 的部分,回到第17行繼續檢查 B 的下一個車廂 } else { // 如果在 station 中沒有找到 need,改在 A 中尋找 need bool find = false; // 是否在 A 當中找到 need,預設為 false while(!A.empty()) { // 如果 A 還有資料則繼續執行 while 迴圈 int a = A.front(); A.pop_front(); // 取出 A 最前方的資料並存入 a if (a == need) { // 如果 a 等於 need,找到了,find 設定為 True,跳出第30行的 while 迴圈 find = true; break; } else { // 如果 a 不等於 need,將 a 加入 station 最後面,繼續檢查 A 的下一個車廂 station.push_back(a); } } if (!find) { // 如果沒有在 A 找到 need,無法達成題目要求的排序 B,flag 設定為 False,跳出第25行的 for 迴圈 flag = false; break; } } } cout << (flag ? "Yes" : "No") << "\n"; // 如果 flag 為 true 印出 Yes,反之印出 No } } } } return 0; } ``` ## [ZeroJudge: a565. 2.p&q的邂逅](https://zerojudge.tw/ShowProblem?problemid=a565) ### Python 程式碼 於第4筆測資會超時。 ```python= import sys n = int(sys.stdin.readline()) for _ in range(n): s = sys.stdin.readline() ps = [] ans = 0 for c in s: if c == 'p': ps.append(1) elif c == 'q' and ps: ps.pop(); ans += 1 print(ans) ``` ### C++ 程式碼 執行時間最久約為 0.2 s,使用記憶體最多約為 25.8 MB,通過測試。 ```cpp= #include <iostream> #include <stack> #include <string> using namespace std; int main() { ios::sync_with_stdio(0),cin.tie(0); int n; cin >> n; string s; for(int i=0; i<n; i++) { stack<int> ps; cin >> s; int ans = 0; for(auto c : s) { if (c == 'p') { ps.push(1); } else if (c == 'q' && !ps.empty()) { ps.pop(); ans++; } } cout << ans << "\n"; } return 0; } ``` ## [ZeroJudge: a813. 4. 城市觀測](https://zerojudge.tw/ShowProblem?problemid=a813) ### Python 程式碼 第三筆測資超時。 ```python= n = int(input()) # 房子數量 hs = [0] + list(map(int, input().split())) # 每一棟房子的高度,開頭加入 0 ans = 0 # 答案預設為 0 for _ in range(0, 2): # 執行2次,前向右掃與左側房子比較高度,再向左掃與右側房子比較高度 st = [] # 放入的資料為 [目前最高的高度, 累計數量] for i in range(1, n+1): # 依序檢查第 1 ~ n 棟房子 while st and st[-1][0] < hs[i]: # 如果 st 還有資料而且 st 最後一項的高度小於第 i 棟房子 ans += st[-1][1] # ans 加上 st 最後一項的累計數量 st.pop() # 移除最後一項 if st and st[-1][0] == hs[i]: # 如果 st 還有資料而且 st 最後一項的高度等於第 i 棟房子 tmp = st.pop() # 暫存 st 最後一項至 tmp 並移除 if st: ans += 1 # 如果 st 還有資料 ans 加 1 ans += tmp[1] # ans 加上 tmp[1] st.append([tmp[0], tmp[1]+1]) # st 最後加上 [tmp 的高度, tmp 原來的數量加 1] else: # 如果 st 沒有資料或是最後一項的高度小於第 i 棟房子 if st: ans += 1 # 如果 st 還有資料 ans 加 1,因為一定能看到隔壁的房子 st.append([hs[i], 1]) # st 最後加上 [第 i 棟房子的高度, 數量為 1] # end of for loop hs[1:].reverse() # 將 hs[1] ~ hs[n] 順序反過來, # end of for loop print(ans) ``` ### C++ 程式碼 執行時間最久約為 0.2 s,使用記憶體最多約為 10.4 MB,通過測試。 ```cpp= #include <iostream> #include <vector> #include <stack> #include <utility> #include <algorithm> typedef long long LL; using namespace std; int main() { ios::sync_with_stdio(0); cin.tie(0); LL n; cin >> n; // 房子數量 vector<LL> hs (n+1, 0); // 每一棟房子的高度,開頭加入 0 for(LL i=1; i<=n; i++) cin >> hs[i]; LL ans = 0; // 答案預設為 0 for(int k=0; k<2; k++) { // 執行2次,前向右掃與左側房子比較高度,再向左掃與右側房子比較高度 stack<pair<LL, LL>> st; // 放入的資料為 {目前最高的高度, 累計數量} for(LL i=1; i<=n; i++) { // 依序檢查第 1 ~ n 棟房子 while(!st.empty() && st.top().first < hs[i]) { // 如果 st 還有資料而且 st 最後一項的高度小於第 i 棟房子 ans += st.top().second; // ans 加上 st 最後一項的累計數量 st.pop(); // 移除最後一項 } if (!st.empty() && st.top().first == hs[i]) { // 如果 st 還有資料而且 st 最後一項的高度等於第 i 棟房子 pair<LL, LL> tmp = st.top(); st.pop(); // 暫存 st 最後一項至 tmp 並移除 if (!st.empty()) ans++; // 如果 st 還有資料 ans 加 1 ans += tmp.second; // ans 加上 tmp.second st.push(make_pair(tmp.first, tmp.second+1)); // st 最後加上 {tmp 的高度, tmp 原來的數量加 1} } else { // 如果 st 沒有資料或是最後一項的高度小於第 i 棟房子 if (!st.empty()) ans++; // 如果 st 還有資料 ans 加 1,因為一定能看到隔壁的房子 st.push(make_pair(hs[i], 1)); // st 最後加上 {第 i 棟房子的高度, 數量為 1} } } reverse(hs.begin()+1, hs.end()); // 將 hs[1] ~ hs[n] 順序反過來, } cout << ans << "\n"; return 0; } ``` ## [ZeroJudge: a664. 四則運算](https://zerojudge.tw/ShowProblem?problemid=a664) ### Python 程式碼 執行時間最久約為 20 ms,使用記憶體最多約為 3.3 MB,通過測試。 ```python= N = int(input()) # 要計算的算式數量 for _ in range(N): # 讀取 N 行算式 s = input() # 由標準輸入讀取算式 func = [] # 儲存算式用的串列 tmp = "" # 暫存數字的字串 for c in s: # 依序由 s 讀取字元 c if c == '(' or c == '+' or c == '-' or c == '*' or c == '/': # 如果 c 是 (+-*/ if tmp: # 如果 tmp 有內容,將 tmp 加到 func 最後面,再清空 tmp func.append(tmp); tmp = "" func.append(c) # 將 c 加到 func 最後面 elif c == ')': # 如果 c 是 ) n = 0 # 暫存數值用的變數 n if tmp: # 如果 tmp 有內容,將 tmp 加到 func 最後面,再清空 tmp func.append(tmp); tmp = "" while func: # 如果 func 有內容,繼續執行直到遇到 ( f = func.pop() # 取出 func 最後一項並存入 f if func[-1] == '(': # 如果 func 目前最後一項是 ( func.pop(); func.append(f); break # 移除 (,將 f 加到 func 最後面,跳出第17行的 while 迴圈 elif f == '+': # 如果 f 是 +,取出 func 最後一項並轉成整數 t,計算 t + n 再轉成字串加到 func 最後面 t = int(func.pop()); func.append(str(t + n)) elif f == '-': # 如果 f 是 -,取出 func 最後一項並轉成整數 t,計算 t - n 再轉成字串加到 func 最後面 t = int(func.pop()); func.append(str(t - n)) elif f == '*': # 如果 f 是 *,取出 func 最後一項並轉成整數 t,計算 t * n 再轉成字串加到 func 最後面 t = int(func.pop()); func.append(str(t * n)) elif f == '/': # 如果 f 是 /,取出 func 最後一項並轉成整數 t,計算 t // n 再轉成字串加到 func 最後面 t = int(func.pop()); func.append(str(t // n)) else: # 如果 f 不是 (+-*/,則 f 是數字,轉成整數並存入 n n = int(f) else: # 如果 c 不是 (+-*/),則 c 是數字,加到 tmp 最後面 tmp += c print(func[0]) # 最後 func 只剩下一個元素,就是計算結果 ``` ### C++ 程式碼 一定要用 long 儲存計算結果,用 int 會溢位。執行時間最久約為 2 ms,使用記憶體最多約為 312 kB,通過測試。 ```cpp= #include <iostream> #include <string> #include <stack> using namespace std; int main() { int N; cin >> N; long n = 0, t = 0; //stack<string> func; string s, ss, f, tmp; for(int i=0; i<N; i++) { stack<string> func; ss.clear(); tmp.clear(); cin >> ss; for(auto c : ss) { s.assign(1, c); if (s == "(" || s == "+" || s == "-" || s == "*" || s == "/") { if (!tmp.empty()) { func.push(tmp); tmp.clear(); } func.push(s); } else if (s == ")") { if (!tmp.empty()) { func.push(tmp); tmp.clear(); } while(!func.empty()) { f = func.top(); func.pop(); if (func.top() == "(") { func.pop(); func.push(f); break; } else if (f == "+") { t = stol(func.top()); func.pop(); func.push(to_string(t + n)); } else if (f == "-") { t = stol(func.top()); func.pop(); func.push(to_string(t - n)); } else if (f == "*") { t = stol(func.top()); func.pop(); func.push(to_string(t * n)); } else if (f == "/") { t = stol(func.top()); func.pop(); func.push(to_string(t / n)); } else { n = stol(f); } } } else { tmp += s; } } cout << func.top() << "\n"; } return 0; } ``` ------ ###### tags:`演算法`、`APCS`、`Python`、`C++`