From 232e85789c9b494f777113135ffdecfeb0b27ec4 Mon Sep 17 00:00:00 2001 From: ryosuketc <43229670+ryosuketc@users.noreply.github.com> Date: Fri, 5 Sep 2025 15:32:25 +0900 Subject: [PATCH] 232. Implement Queue using Stacks https://leetcode.com/problems/implement-queue-using-stacks/ --- 232_implement_queue_using_stacks/memo.md | 42 ++++++++++ 232_implement_queue_using_stacks/step1.cpp | 54 ++++++++++++ 232_implement_queue_using_stacks/step2.cpp | 95 ++++++++++++++++++++++ 232_implement_queue_using_stacks/step3.cpp | 38 +++++++++ 4 files changed, 229 insertions(+) create mode 100644 232_implement_queue_using_stacks/memo.md create mode 100644 232_implement_queue_using_stacks/step1.cpp create mode 100644 232_implement_queue_using_stacks/step2.cpp create mode 100644 232_implement_queue_using_stacks/step3.cpp diff --git a/232_implement_queue_using_stacks/memo.md b/232_implement_queue_using_stacks/memo.md new file mode 100644 index 0000000..5a0ce6d --- /dev/null +++ b/232_implement_queue_using_stacks/memo.md @@ -0,0 +1,42 @@ +# 232. Implement Queue using Stacks + +https://leetcode.com/problems/implement-queue-using-stacks/ + +## Comments + +### step1 + +* 久々に取り組んだ +* 問題文から、2 つ stack を使うことが明らかだったので、その方針で考えてみた。 +* 一旦移して順番を入れ替える (reverse) はまあ思いついて、ただ O(n) なんだよな、と思いつつ、O(1) がないか 3:00 くらい考えたが思いつかなかった。 +* `st`, `st_aux` よりはいい名前があるだろうと思ったが、あまり思いつかなかったのでこのまま + * 最初 `stack`, `stack_aux` としていたが、`std::stack` と衝突する +* 最初、`pop` の方で入れ替え処理を書こうとして、数行書いたあたりで、`pop` する処理と混ざって面倒なので、`push` で書いたほうがいいかな、と思った + * l11-14, 別になくても動くなと、後から読み直して気付いた + * 後から考えると、おそらく一般的なユースケースでは `pop` の方が頻度が低そうなので、そちらを O(n)、`push` を O(1) 二死したほうがよかったのかもしれない +* `peek`, `pop` の empty check はメソッドにしてもいい + * ただそれ以前に例外を投げていいのかちょっと迷った (https://github.com/ryosuketc/leetcode_grind75/pull/10#discussion_r2295004606) + * ただ今回だと int を返さなければならないが、"特殊な int" というのが思いつかなかった。どのような int でも queue に入る可能性があるので、特定の int をエラーとして扱うのは無理がある + * ので結局今回は例外を選択 +* 最初、Python のクセか、`st`, `st_aux` をコンストラクタ内で定義して怒られた。 + * C++ だと、宣言と初期化が分離している (コンストラクタでは初期化を行う) + +### step2 + +* https://leetcode.com/problems/implement-queue-using-stacks/editorial/ + * amortized O(1) の書き方があるらしい。 + * なるほど、普段は `st` に LIFO のまま push しておく + * `pop` が呼ばれたとき、**かつ `st_aux` が空の場合のみ**に一気に `st_aux` に移す。`st_aux` に要素が残っていれば (`st_aux` は FIFO で積んでいるので) 単純に top を返して pop すればよい。 + * `front` で状態管理しようとして失敗した (`MyQueue1`) +* Gemini と相談したりあれこれしてたらこの実装が良さそう (`MyQueue2`) + * `front` による状態管理はしない + * `st`, `st_aux` は役割的に `stack_in`, `stack_out` がよさそう。省略形 `st` も避けておく + * `stack_in`, `stack_out` 間の処理を `peek` に移動し、`pop` から `peek` を呼ぶようにした + * このクラスの `empty()` を利用。 + * `exception` + * https://en.cppreference.com/w/cpp/error/exception.html + * C++ だと上のような standard exceptions がある。まだぜんぶは覚えてないけど + * C++ 例外も Python と同様に階層構造があるようだ。上位のものを指定すると下位をまとめて catch できる (はず) + +### step3 +* `step2.MyQueue2` と同じ diff --git a/232_implement_queue_using_stacks/step1.cpp b/232_implement_queue_using_stacks/step1.cpp new file mode 100644 index 0000000..e5657c8 --- /dev/null +++ b/232_implement_queue_using_stacks/step1.cpp @@ -0,0 +1,54 @@ +class MyQueue { +private: + // stack holds items in quque fashion. + std::stack st; + std::stack st_aux; +public: + MyQueue() { + } + + void push(int x) { + if (st.empty()) { + st.push(x); + return; + } + while (!st.empty()) { + st_aux.push(st.top()); + st.pop(); + } + st_aux.push(x); + while (!st_aux.empty()) { + st.push(st_aux.top()); + st_aux.pop(); + } + } + + int pop() { + if (st.empty()) { + throw std::out_of_range("Queue is empty"); + } + int top = st.top(); + st.pop(); + return top; + } + + int peek() { + if (st.empty()) { + throw std::out_of_range("Queue is empty"); + } + return st.top(); + } + + bool empty() { + return st.empty(); + } +}; + +/** + * Your MyQueue object will be instantiated and called as such: + * MyQueue* obj = new MyQueue(); + * obj->push(x); + * int param_2 = obj->pop(); + * int param_3 = obj->peek(); + * bool param_4 = obj->empty(); + */ diff --git a/232_implement_queue_using_stacks/step2.cpp b/232_implement_queue_using_stacks/step2.cpp new file mode 100644 index 0000000..0f24a6f --- /dev/null +++ b/232_implement_queue_using_stacks/step2.cpp @@ -0,0 +1,95 @@ + +// 動かないコード。 +// front で状態管理しようとして失敗した。デバッグしようとして面倒になったのでやめた。 +#include + +class MyQueue1 { +private: + std::stack st; + std::stack st_aux; + int front; +public: + MyQueue() { + } + + void push(int x) { + if (st.empty() && st_aux.empty()) { + front = x; + } + st.push(x); + } + + int pop() { + if (st.empty() && st_aux.empty()) { + throw std::out_of_range("Queue is empty"); + } + if (st_aux.empty()) { + while (!st.empty()) { + st_aux.push(st.top()); + st.pop(); + } + } + int popped_item = st_aux.top(); + st_aux.pop(); + // Update the front. + if (!st_aux.empty()) { + front = st_aux.top(); + } + return popped_item; + } + + int peek() { + return front; + } + + bool empty() { + return st.empty() && st_aux.empty(); + } +}; + +/** + * Your MyQueue object will be instantiated and called as such: + * MyQueue* obj = new MyQueue(); + * obj->push(x); + * int param_2 = obj->pop(); + * int param_3 = obj->peek(); + * bool param_4 = obj->empty(); + */ + +#include + + class MyQueue2 { + std::stack stack_in; + std::stack stack_out; +public: + MyQueue() { + } + + void push(int x) { + stack_in.push(x); + } + + int pop() { + int front = peek(); + stack_out.pop(); + return front; + } + + int peek() { + if (empty()) { + throw std::out_of_range("Queue is empty"); + } + if (stack_out.empty()) { + while (!stack_in.empty()) { + stack_out.push(stack_in.top()); + stack_in.pop(); + } + } + return stack_out.top(); + } + + bool empty() { + return stack_in.empty() && stack_out.empty(); + } +}; + diff --git a/232_implement_queue_using_stacks/step3.cpp b/232_implement_queue_using_stacks/step3.cpp new file mode 100644 index 0000000..f831ac9 --- /dev/null +++ b/232_implement_queue_using_stacks/step3.cpp @@ -0,0 +1,38 @@ + +#include + + class MyQueue2 { + std::stack stack_in; + std::stack stack_out; +public: + MyQueue() { + } + + void push(int x) { + stack_in.push(x); + } + + int pop() { + int front = peek(); + stack_out.pop(); + return front; + } + + int peek() { + if (empty()) { + throw std::out_of_range("Queue is empty"); + } + if (stack_out.empty()) { + while (!stack_in.empty()) { + stack_out.push(stack_in.top()); + stack_in.pop(); + } + } + return stack_out.top(); + } + + bool empty() { + return stack_in.empty() && stack_out.empty(); + } +}; +