Skip to content

Commit a99f4c4

Browse files
committed
feat: add Implement Queue using Stacks
1 parent 76581dc commit a99f4c4

File tree

13 files changed

+479
-1
lines changed

13 files changed

+479
-1
lines changed
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
{
2+
"problem_name": "implement_queue_using_stacks",
3+
"solution_class_name": "MyQueue",
4+
"problem_number": "232",
5+
"problem_title": "Implement Queue using Stacks",
6+
"difficulty": "Easy",
7+
"topics": "Stack, Design, Queue",
8+
"tags": ["grind-75"],
9+
"readme_description": "Implement a first in first out (FIFO) queue using only two stacks. The implemented queue should support all the functions of a normal queue (`push`, `peek`, `pop`, and `empty`).\n\nImplement the `MyQueue` class:\n\n- `void push(int x)` Pushes element x to the back of the queue.\n- `int pop()` Removes the element from the front of the queue and returns it.\n- `int peek()` Returns the element at the front of the queue.\n- `boolean empty()` Returns `true` if the queue is empty, `false` otherwise.",
10+
"readme_examples": [
11+
{
12+
"content": "```\nInput\n[\"MyQueue\", \"push\", \"push\", \"peek\", \"pop\", \"empty\"]\n[[], [1], [2], [], [], []]\nOutput\n[null, null, null, 1, 1, false]\n```\n**Explanation:**\n```\nMyQueue myQueue = new MyQueue();\nmyQueue.push(1); // queue is: [1]\nmyQueue.push(2); // queue is: [1, 2] (leftmost is front of the queue)\nmyQueue.peek(); // return 1\nmyQueue.pop(); // return 1, queue is [2]\nmyQueue.empty(); // return false\n```"
13+
}
14+
],
15+
"readme_constraints": "- 1 <= x <= 9\n- At most 100 calls will be made to push, pop, peek, and empty.\n- All the calls to pop and peek are valid.",
16+
"readme_additional": "**Notes:**\n- You must use **only** standard operations of a stack, which means only `push to top`, `peek/pop from top`, `size`, and `is empty` operations are valid.\n- Depending on your language, the stack may not be supported natively. You may simulate a stack using a list or deque (double-ended queue) as long as you use only a stack's standard operations.\n\n**Follow-up:** Can you implement the queue such that each operation is amortized `O(1)` time complexity? In other words, performing `n` operations will take overall `O(n)` time even if one of those operations may take longer.",
17+
"solution_imports": "",
18+
"solution_methods": [
19+
{ "name": "__init__", "parameters": "", "return_type": "None", "dummy_return": "" },
20+
{ "name": "push", "parameters": "x: int", "return_type": "None", "dummy_return": "" },
21+
{ "name": "pop", "parameters": "", "return_type": "int", "dummy_return": "0" },
22+
{ "name": "peek", "parameters": "", "return_type": "int", "dummy_return": "0" },
23+
{ "name": "empty", "parameters": "", "return_type": "bool", "dummy_return": "True" }
24+
],
25+
"test_imports": "import pytest\nfrom leetcode_py.test_utils import logged_test\nfrom .solution import MyQueue",
26+
"test_class_name": "ImplementQueueUsingStacks",
27+
"test_helper_methods": [],
28+
"test_methods": [
29+
{
30+
"name": "test_queue_operations",
31+
"parametrize": "operations, inputs, expected",
32+
"parametrize_typed": "operations: list[str], inputs: list[list[int]], expected: list[int | None | bool]",
33+
"test_cases": "[(['MyQueue', 'push', 'push', 'peek', 'pop', 'empty'], [[], [1], [2], [], [], []], [None, None, None, 1, 1, False]), (['MyQueue', 'empty', 'push', 'peek', 'pop', 'empty'], [[], [], [1], [], [], []], [None, True, None, 1, 1, True]), (['MyQueue', 'push', 'push', 'push', 'pop', 'pop', 'peek', 'pop', 'empty'], [[], [1], [2], [3], [], [], [], [], []], [None, None, None, None, 1, 2, 3, 3, True])]",
34+
"body": "queue = None\nresults: list[int | None | bool] = []\nfor i, op in enumerate(operations):\n if op == 'MyQueue':\n queue = MyQueue()\n results.append(None)\n elif op == 'push' and queue is not None:\n queue.push(inputs[i][0])\n results.append(None)\n elif op == 'pop' and queue is not None:\n results.append(queue.pop())\n elif op == 'peek' and queue is not None:\n results.append(queue.peek())\n elif op == 'empty' and queue is not None:\n results.append(queue.empty())\nassert results == expected"
35+
}
36+
],
37+
"playground_imports": "from solution import MyQueue",
38+
"playground_test_case": "# Example test case\nqueue = MyQueue()\nqueue.push(1)\nqueue.push(2)",
39+
"playground_execution": "result_peek = queue.peek()\nresult_pop = queue.pop()\nresult_empty = queue.empty()\nprint(f'peek: {result_peek}, pop: {result_pop}, empty: {result_empty}')",
40+
"playground_assertion": "assert result_peek == 1\nassert result_pop == 1\nassert result_empty == False"
41+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
{
2+
"problem_name": "valid_anagram",
3+
"solution_class_name": "Solution",
4+
"problem_number": "242",
5+
"problem_title": "Valid Anagram",
6+
"difficulty": "Easy",
7+
"topics": "Hash Table, String, Sorting",
8+
"tags": ["grind-75"],
9+
"readme_description": "Given two strings `s` and `t`, return `true` if `t` is an anagram of `s`, and `false` otherwise.",
10+
"readme_examples": [
11+
{ "content": "```\nInput: s = \"anagram\", t = \"nagaram\"\nOutput: true\n```" },
12+
{ "content": "```\nInput: s = \"rat\", t = \"car\"\nOutput: false\n```" }
13+
],
14+
"readme_constraints": "- 1 <= s.length, t.length <= 5 * 10^4\n- s and t consist of lowercase English letters.",
15+
"readme_additional": "**Follow up:** What if the inputs contain Unicode characters? How would you adapt your solution to such a case?",
16+
"solution_imports": "",
17+
"solution_methods": [
18+
{
19+
"name": "is_anagram",
20+
"parameters": "s: str, t: str",
21+
"return_type": "bool",
22+
"dummy_return": "False"
23+
}
24+
],
25+
"test_imports": "import pytest\nfrom leetcode_py.test_utils import logged_test\nfrom .solution import Solution",
26+
"test_class_name": "ValidAnagram",
27+
"test_helper_methods": [
28+
{ "name": "setup_method", "parameters": "", "body": "self.solution = Solution()" }
29+
],
30+
"test_methods": [
31+
{
32+
"name": "test_is_anagram",
33+
"parametrize": "s, t, expected",
34+
"parametrize_typed": "s: str, t: str, expected: bool",
35+
"test_cases": "[('anagram', 'nagaram', True), ('rat', 'car', False), ('listen', 'silent', True), ('hello', 'bello', False), ('', '', True), ('a', 'a', True), ('a', 'b', False), ('ab', 'ba', True)]",
36+
"body": "result = self.solution.is_anagram(s, t)\nassert result == expected"
37+
}
38+
],
39+
"playground_imports": "from solution import Solution",
40+
"playground_test_case": "# Example test case\ns = 'anagram'\nt = 'nagaram'\nexpected = True",
41+
"playground_execution": "result = Solution().is_anagram(s, t)\nresult",
42+
"playground_assertion": "assert result == expected"
43+
}

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
PYTHON_VERSION = 3.13
2-
PROBLEM ?= best_time_to_buy_and_sell_stock
2+
PROBLEM ?= implement_queue_using_stacks
33
FORCE ?= 0
44
COMMA := ,
55

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Implement Queue using Stacks
2+
3+
**Difficulty:** Easy
4+
**Topics:** Stack, Design, Queue
5+
**Tags:** grind-75
6+
7+
**LeetCode:** [Problem 232](https://leetcode.com/problems/implement-queue-using-stacks/description/)
8+
9+
## Problem Description
10+
11+
Implement a first in first out (FIFO) queue using only two stacks. The implemented queue should support all the functions of a normal queue (`push`, `peek`, `pop`, and `empty`).
12+
13+
Implement the `MyQueue` class:
14+
15+
- `void push(int x)` Pushes element x to the back of the queue.
16+
- `int pop()` Removes the element from the front of the queue and returns it.
17+
- `int peek()` Returns the element at the front of the queue.
18+
- `boolean empty()` Returns `true` if the queue is empty, `false` otherwise.
19+
20+
## Examples
21+
22+
### Example 1:
23+
24+
```
25+
Input
26+
["MyQueue", "push", "push", "peek", "pop", "empty"]
27+
[[], [1], [2], [], [], []]
28+
Output
29+
[null, null, null, 1, 1, false]
30+
```
31+
32+
**Explanation:**
33+
34+
```
35+
MyQueue myQueue = new MyQueue();
36+
myQueue.push(1); // queue is: [1]
37+
myQueue.push(2); // queue is: [1, 2] (leftmost is front of the queue)
38+
myQueue.peek(); // return 1
39+
myQueue.pop(); // return 1, queue is [2]
40+
myQueue.empty(); // return false
41+
```
42+
43+
## Constraints
44+
45+
- 1 <= x <= 9
46+
- At most 100 calls will be made to push, pop, peek, and empty.
47+
- All the calls to pop and peek are valid.
48+
49+
**Notes:**
50+
51+
- You must use **only** standard operations of a stack, which means only `push to top`, `peek/pop from top`, `size`, and `is empty` operations are valid.
52+
- Depending on your language, the stack may not be supported natively. You may simulate a stack using a list or deque (double-ended queue) as long as you use only a stack's standard operations.
53+
54+
**Follow-up:** Can you implement the queue such that each operation is amortized `O(1)` time complexity? In other words, performing `n` operations will take overall `O(n)` time even if one of those operations may take longer.

leetcode/implement_queue_using_stacks/__init__.py

Whitespace-only changes.
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "code",
5+
"execution_count": 2,
6+
"id": "imports",
7+
"metadata": {},
8+
"outputs": [],
9+
"source": [
10+
"from solution import MyQueue"
11+
]
12+
},
13+
{
14+
"cell_type": "code",
15+
"execution_count": 3,
16+
"id": "setup",
17+
"metadata": {},
18+
"outputs": [],
19+
"source": [
20+
"# Example test case\n",
21+
"queue = MyQueue()\n",
22+
"queue.push(1)\n",
23+
"queue.push(2)"
24+
]
25+
},
26+
{
27+
"cell_type": "code",
28+
"execution_count": 4,
29+
"id": "execute",
30+
"metadata": {},
31+
"outputs": [
32+
{
33+
"name": "stdout",
34+
"output_type": "stream",
35+
"text": [
36+
"peek: 1, pop: 1, empty: False\n"
37+
]
38+
}
39+
],
40+
"source": [
41+
"result_peek = queue.peek()\n",
42+
"result_pop = queue.pop()\n",
43+
"result_empty = queue.empty()\n",
44+
"print(f\"peek: {result_peek}, pop: {result_pop}, empty: {result_empty}\")"
45+
]
46+
},
47+
{
48+
"cell_type": "code",
49+
"execution_count": 5,
50+
"id": "test",
51+
"metadata": {},
52+
"outputs": [],
53+
"source": [
54+
"assert result_peek == 1\n",
55+
"assert result_pop == 1\n",
56+
"assert not result_empty"
57+
]
58+
}
59+
],
60+
"metadata": {
61+
"kernelspec": {
62+
"display_name": "leetcode-py-py3.13",
63+
"language": "python",
64+
"name": "python3"
65+
},
66+
"language_info": {
67+
"codemirror_mode": {
68+
"name": "ipython",
69+
"version": 3
70+
},
71+
"file_extension": ".py",
72+
"mimetype": "text/x-python",
73+
"name": "python",
74+
"nbconvert_exporter": "python",
75+
"pygments_lexer": "ipython3",
76+
"version": "3.13.7"
77+
}
78+
},
79+
"nbformat": 4,
80+
"nbformat_minor": 5
81+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
class MyQueue:
2+
# Time: O(1)
3+
# Space: O(n)
4+
def __init__(self) -> None:
5+
self.input_stack: list[int] = []
6+
self.output_stack: list[int] = []
7+
8+
# Time: O(1)
9+
# Space: O(1)
10+
def push(self, x: int) -> None:
11+
self.input_stack.append(x)
12+
13+
# Time: O(1) amortized
14+
# Space: O(1)
15+
def pop(self) -> int:
16+
self._move_to_output()
17+
return self.output_stack.pop()
18+
19+
# Time: O(1) amortized
20+
# Space: O(1)
21+
def peek(self) -> int:
22+
self._move_to_output()
23+
return self.output_stack[-1]
24+
25+
# Time: O(1)
26+
# Space: O(1)
27+
def empty(self) -> bool:
28+
return not self.input_stack and not self.output_stack
29+
30+
def _move_to_output(self) -> None:
31+
if not self.output_stack:
32+
while self.input_stack:
33+
self.output_stack.append(self.input_stack.pop())
34+
35+
36+
# Amortized O(1) Explanation:
37+
# Example with 4 push + 4 pop operations:
38+
#
39+
# push(1) # input: [1], output: [] - O(1)
40+
# push(2) # input: [1,2], output: [] - O(1)
41+
# push(3) # input: [1,2,3], output: [] - O(1)
42+
# push(4) # input: [1,2,3,4], output: [] - O(1)
43+
#
44+
# pop() # Move all 4 to output: input: [], output: [4,3,2,1] then pop 1 - O(4)
45+
# pop() # output: [4,3,2], just pop 2 - O(1)
46+
# pop() # output: [4,3], just pop 3 - O(1)
47+
# pop() # output: [4], just pop 4 - O(1)
48+
#
49+
# Total cost: 4 + 4 + 1 + 1 + 1 = 11 operations for 8 calls = 1.4 per operation
50+
# Key: Each element moves exactly once from input to output, so expensive O(n)
51+
# transfer is "spread out" over multiple cheap O(1) operations = amortized O(1)
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import pytest
2+
3+
from leetcode_py.test_utils import logged_test
4+
5+
from .solution import MyQueue
6+
7+
8+
class TestImplementQueueUsingStacks:
9+
@pytest.mark.parametrize(
10+
"operations, inputs, expected",
11+
[
12+
(
13+
["MyQueue", "push", "push", "peek", "pop", "empty"],
14+
[[], [1], [2], [], [], []],
15+
[None, None, None, 1, 1, False],
16+
),
17+
(
18+
["MyQueue", "empty", "push", "peek", "pop", "empty"],
19+
[[], [], [1], [], [], []],
20+
[None, True, None, 1, 1, True],
21+
),
22+
(
23+
["MyQueue", "push", "push", "push", "pop", "pop", "peek", "pop", "empty"],
24+
[[], [1], [2], [3], [], [], [], [], []],
25+
[None, None, None, None, 1, 2, 3, 3, True],
26+
),
27+
],
28+
)
29+
@logged_test
30+
def test_queue_operations(
31+
self, operations: list[str], inputs: list[list[int]], expected: list[int | None | bool]
32+
):
33+
queue = None
34+
results: list[int | None | bool] = []
35+
for i, op in enumerate(operations):
36+
if op == "MyQueue":
37+
queue = MyQueue()
38+
results.append(None)
39+
elif op == "push" and queue is not None:
40+
queue.push(inputs[i][0])
41+
results.append(None)
42+
elif op == "pop" and queue is not None:
43+
results.append(queue.pop())
44+
elif op == "peek" and queue is not None:
45+
results.append(queue.peek())
46+
elif op == "empty" and queue is not None:
47+
results.append(queue.empty())
48+
assert results == expected

leetcode/valid_anagram/README.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Valid Anagram
2+
3+
**Difficulty:** Easy
4+
**Topics:** Hash Table, String, Sorting
5+
**Tags:** grind-75
6+
7+
**LeetCode:** [Problem 242](https://leetcode.com/problems/valid-anagram/description/)
8+
9+
## Problem Description
10+
11+
Given two strings `s` and `t`, return `true` if `t` is an anagram of `s`, and `false` otherwise.
12+
13+
## Examples
14+
15+
### Example 1:
16+
17+
```
18+
Input: s = "anagram", t = "nagaram"
19+
Output: true
20+
```
21+
22+
### Example 2:
23+
24+
```
25+
Input: s = "rat", t = "car"
26+
Output: false
27+
```
28+
29+
## Constraints
30+
31+
- 1 <= s.length, t.length <= 5 \* 10^4
32+
- s and t consist of lowercase English letters.
33+
34+
**Follow up:** What if the inputs contain Unicode characters? How would you adapt your solution to such a case?

leetcode/valid_anagram/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)