mirror of
https://github.com/krahets/hello-algo.git
synced 2026-07-22 11:26:07 +00:00
4.1 KiB
4.1 KiB
練習
知識鞏固
堆疊和佇列會先取出誰
準備一個空堆疊 S 和一個空佇列 Q,分別對它們執行下面同一組操作:
步驟 1:加入 A;
步驟 2:加入 B;
步驟 3:移除一個元素並記錄;
步驟 4:加入 C;
步驟 5:不斷移除並記錄,直到容器為空。
請分別寫出 S 和 Q 中元素被移除的順序,並用“先入後出”或“先入先出”解釋差異。
??? success "參考答案"
堆疊 `S` 的移除順序是 `B、C、A`:加入 `A、B` 後先彈出最近加入的 `B`,再加入 `C`,
此後依次彈出 `C、A`,體現“先入後出”。
佇列 `Q` 的移除順序是 `A、B、C`:加入 `A、B` 後先移除最早加入的 `A`,
再加入 `C`,此後依次移除 `B、C`,體現“先入先出”。
佇列尾越過陣列末尾怎麼辦
用長度為 5 的環形陣列實現佇列,陣列索引為 0~4。
當前 front = 3、size = 2,佇列中的 A、B 分別位於索引 3、4。
- 執行“
C入列”時,C應放在哪個索引?入列後size是多少? - 接著執行一次出列,彈出哪個元素?新的
front和size分別是多少? - 此時從佇列首到佇列尾的邏輯順序是什麼?出列時是否需要移動陣列中的其他元素?為什麼?
??? success "參考答案"
1. 新元素的位置為
`(front + size) % 5 = (3 + 2) % 5 = 0`,
所以 `C` 放在索引 0。入列後 `size = 3`。
2. 出列彈出當前佇列首 `A`。新的佇列首索引為
`(3 + 1) % 5 = 4`,因此 `front = 4`、`size = 2`。
3. 有效元素的邏輯順序為 `B、C`,其中 `B` 位於索引 4,`C` 位於索引 0。
出列時只需移動 `front` 並修改 `size`,環形陣列用取餘讓索引回到開頭,
因此無須把其他元素整體向前移動。
雙向佇列的兩端操作
這裡規定:push_first 表示從佇列首加入,push_last 表示從佇列尾加入,
pop_first 表示從佇列首彈出,pop_last 表示從佇列尾彈出。
對一個空的雙向佇列 deq 依次執行:
push_last(A)push_last(B)push_first(C)pop_last()push_last(D)pop_first()
- 兩次彈出的元素分別是什麼?
- 全部操作完成後,從佇列首到佇列尾還剩哪些元素?
- 檢查這 6 步操作:只允許從佇列尾加入、從佇列首刪除的佇列能否全部完成?如果不能,請指出無法完成的操作;再說明雙向佇列能否完成及其原因。
??? success "參考答案"
前三步後,雙向佇列從佇列首到佇列尾為 `[C, A, B]`。
<!-- numbered-subquestions -->
1. `pop_last()` 彈出 `B`;加入 `D` 後佇列為 `[C, A, D]`,
`pop_first()` 再彈出 `C`。
2. 最後剩下 `[A, D]`。
3. 只允許在佇列尾新增、在佇列首刪除的佇列不能完成全部操作:
第 3 步 `push_first(C)` 要求從佇列首加入,第 4 步 `pop_last()` 要求從佇列尾刪除,都超出了這種佇列的操作範圍。
雙向佇列的兩端都可以新增和刪除,因此能夠完成這 6 步操作。
程式設計練習
檢查括號序列
給定一個只包含 ()、[]、{} 這三類括號的字串 s,請使用堆疊判斷它是否合法。
合法序列須同時滿足:每個右括號都必須與最近一個尚未配對的左括號型別匹配, 並且走訪結束後沒有未配對的左括號。返回布林值表示判斷結果。
??? tip "解題提示"
1. 可以建立“右括號到對應左括號”的對映
2. 遇到右括號時,先檢查堆疊是否為空,再檢查堆疊頂是否匹配
3. 走訪結束後,堆疊也必須為空
LeetCode{ .rounded-button .exercise-button target="_blank" rel="noopener noreferrer" } 題目解析{ .rounded-button .exercise-button target="_blank" rel="noopener noreferrer" }