Skip to content

Commit 350404c

Browse files
committed
feat: add Reverse Linked List
1 parent 614ad1a commit 350404c

File tree

7 files changed

+298
-1
lines changed

7 files changed

+298
-1
lines changed
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
{
2+
"problem_name": "reverse_linked_list",
3+
"solution_class_name": "Solution",
4+
"problem_number": "206",
5+
"problem_title": "Reverse Linked List",
6+
"difficulty": "Easy",
7+
"topics": "Linked List, Recursion",
8+
"tags": ["grind-75"],
9+
"readme_description": "Given the `head` of a singly linked list, reverse the list, and return the reversed list.",
10+
"readme_examples": [
11+
{
12+
"content": "![Example 1](https://assets.leetcode.com/uploads/2021/02/19/rev1ex1.jpg)\n\n```\nInput: head = [1,2,3,4,5]\nOutput: [5,4,3,2,1]\n```"
13+
},
14+
{
15+
"content": "![Example 2](https://assets.leetcode.com/uploads/2021/02/19/rev1ex2.jpg)\n\n```\nInput: head = [1,2]\nOutput: [2,1]\n```"
16+
},
17+
{ "content": "```\nInput: head = []\nOutput: []\n```" }
18+
],
19+
"readme_constraints": "- The number of nodes in the list is the range `[0, 5000]`.\n- `-5000 <= Node.val <= 5000`",
20+
"readme_additional": "**Follow up:** A linked list can be reversed either iteratively or recursively. Could you implement both?",
21+
"solution_imports": "from leetcode_py import ListNode",
22+
"solution_methods": [
23+
{
24+
"name": "reverse_list",
25+
"parameters": "head: ListNode[int] | None",
26+
"return_type": "ListNode[int] | None",
27+
"dummy_return": "None"
28+
}
29+
],
30+
"test_imports": "import pytest\nfrom leetcode_py.test_utils import logged_test\nfrom leetcode_py import ListNode\nfrom .solution import Solution",
31+
"test_class_name": "ReverseLinkedList",
32+
"test_helper_methods": [
33+
{ "name": "setup_method", "parameters": "", "body": "self.solution = Solution()" }
34+
],
35+
"test_methods": [
36+
{
37+
"name": "test_reverse_list",
38+
"parametrize": "head_list, expected_list",
39+
"parametrize_typed": "head_list: list[int], expected_list: list[int]",
40+
"test_cases": "[([1, 2, 3, 4, 5], [5, 4, 3, 2, 1]), ([1, 2], [2, 1]), ([1], [1]), ([], []), ([1, 2, 3], [3, 2, 1]), ([1, 2, 3, 4], [4, 3, 2, 1]), ([-1, -2, -3], [-3, -2, -1]), ([0], [0]), ([5000, -5000], [-5000, 5000]), ([1, 1, 1], [1, 1, 1])]",
41+
"body": "head = ListNode.from_list(head_list)\nexpected = ListNode.from_list(expected_list)\nresult = self.solution.reverse_list(head)\nassert result == expected"
42+
}
43+
],
44+
"playground_imports": "from leetcode_py import ListNode\nfrom solution import Solution",
45+
"playground_test_case": "# Example test case\nhead_list = [1, 2, 3, 4, 5]\nexpected_list = [5, 4, 3, 2, 1]\nhead = ListNode.from_list(head_list)\nexpected = ListNode.from_list(expected_list)",
46+
"playground_execution": "result = Solution().reverse_list(head)\nresult",
47+
"playground_assertion": "assert result == expected"
48+
}

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 ?= merge_intervals
2+
PROBLEM ?= reverse_linked_list
33
FORCE ?= 0
44
COMMA := ,
55

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Reverse Linked List
2+
3+
**Difficulty:** Easy
4+
**Topics:** Linked List, Recursion
5+
**Tags:** grind-75
6+
7+
**LeetCode:** [Problem 206](https://leetcode.com/problems/reverse-linked-list/description/)
8+
9+
## Problem Description
10+
11+
Given the `head` of a singly linked list, reverse the list, and return the reversed list.
12+
13+
## Examples
14+
15+
### Example 1:
16+
17+
![Example 1](https://assets.leetcode.com/uploads/2021/02/19/rev1ex1.jpg)
18+
19+
```
20+
Input: head = [1,2,3,4,5]
21+
Output: [5,4,3,2,1]
22+
```
23+
24+
### Example 2:
25+
26+
![Example 2](https://assets.leetcode.com/uploads/2021/02/19/rev1ex2.jpg)
27+
28+
```
29+
Input: head = [1,2]
30+
Output: [2,1]
31+
```
32+
33+
### Example 3:
34+
35+
```
36+
Input: head = []
37+
Output: []
38+
```
39+
40+
## Constraints
41+
42+
- The number of nodes in the list is the range `[0, 5000]`.
43+
- `-5000 <= Node.val <= 5000`
44+
45+
**Follow up:** A linked list can be reversed either iteratively or recursively. Could you implement both?

leetcode/reverse_linked_list/__init__.py

Whitespace-only changes.
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "code",
5+
"execution_count": 1,
6+
"id": "imports",
7+
"metadata": {},
8+
"outputs": [],
9+
"source": [
10+
"from solution import Solution\n",
11+
"\n",
12+
"from leetcode_py import ListNode"
13+
]
14+
},
15+
{
16+
"cell_type": "code",
17+
"execution_count": 2,
18+
"id": "setup",
19+
"metadata": {},
20+
"outputs": [
21+
{
22+
"name": "stdout",
23+
"output_type": "stream",
24+
"text": [
25+
"Original: [1, 2, 3, 4, 5]\n",
26+
"Expected: [5, 4, 3, 2, 1]\n"
27+
]
28+
}
29+
],
30+
"source": [
31+
"# Example test case: reverse [1,2,3,4,5] to [5,4,3,2,1]\n",
32+
"head_list = [1, 2, 3, 4, 5]\n",
33+
"expected_list = [5, 4, 3, 2, 1]\n",
34+
"\n",
35+
"# Convert lists to linked lists\n",
36+
"head = ListNode.from_list(head_list)\n",
37+
"expected = ListNode.from_list(expected_list)\n",
38+
"print(f\"Original: {head}\")\n",
39+
"print(f\"Expected: {expected}\")"
40+
]
41+
},
42+
{
43+
"cell_type": "code",
44+
"execution_count": null,
45+
"id": "execute",
46+
"metadata": {},
47+
"outputs": [
48+
{
49+
"name": "stdout",
50+
"output_type": "stream",
51+
"text": [
52+
"Result: [5, 4, 3, 2, 1]\n"
53+
]
54+
},
55+
{
56+
"data": {
57+
"text/plain": [
58+
"[5, 4, 3, 2, 1]"
59+
]
60+
},
61+
"execution_count": 3,
62+
"metadata": {},
63+
"output_type": "execute_result"
64+
}
65+
],
66+
"source": [
67+
"# Reverse the linked list: 1->2->3->4->5 becomes 5->4->3->2->1\n",
68+
"result = Solution().reverse_list(head)\n",
69+
"print(f\"Result: {result}\")\n",
70+
"result"
71+
]
72+
},
73+
{
74+
"cell_type": "code",
75+
"execution_count": 4,
76+
"id": "test",
77+
"metadata": {},
78+
"outputs": [
79+
{
80+
"name": "stdout",
81+
"output_type": "stream",
82+
"text": [
83+
"✅ Test passed! Linked list successfully reversed.\n"
84+
]
85+
}
86+
],
87+
"source": [
88+
"# Verify the result matches expected output\n",
89+
"assert result == expected"
90+
]
91+
}
92+
],
93+
"metadata": {
94+
"kernelspec": {
95+
"display_name": "leetcode-py-py3.13",
96+
"language": "python",
97+
"name": "python3"
98+
},
99+
"language_info": {
100+
"codemirror_mode": {
101+
"name": "ipython",
102+
"version": 3
103+
},
104+
"file_extension": ".py",
105+
"mimetype": "text/x-python",
106+
"name": "python",
107+
"nbconvert_exporter": "python",
108+
"pygments_lexer": "ipython3",
109+
"version": "3.13.7"
110+
}
111+
},
112+
"nbformat": 4,
113+
"nbformat_minor": 5
114+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
from leetcode_py import ListNode
2+
3+
4+
class Solution:
5+
# Time: O(n)
6+
# Space: O(1)
7+
def reverse_list(self, head: ListNode[int] | None) -> ListNode[int] | None:
8+
if not head:
9+
return None
10+
11+
# Iterative approach using three pointers
12+
# Example: [1,2,3] -> [3,2,1]
13+
#
14+
# Initial: prev curr
15+
# None ↓
16+
# 1 -> 2 -> 3 -> None
17+
#
18+
prev: ListNode[int] | None = None
19+
curr: ListNode[int] | None = head
20+
21+
while curr:
22+
# Store next node before breaking the link
23+
next_node = curr.next
24+
#
25+
# prev curr next_node
26+
# None ↓ ↓
27+
# 1 -> 2 -> 3 -> None
28+
#
29+
30+
# Reverse the current link
31+
curr.next = prev
32+
# None <- 1 2 -> 3 -> None
33+
# prev curr next_node
34+
#
35+
36+
# Move pointers forward
37+
prev = curr
38+
curr = next_node
39+
# 1 <- 2 3 -> None
40+
# prev curr
41+
#
42+
43+
# 1 <- 2 <- 3 None
44+
# prev curr
45+
# prev now points to new head of reversed list
46+
return prev
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import pytest
2+
3+
from leetcode_py import ListNode
4+
from leetcode_py.test_utils import logged_test
5+
6+
from .solution import Solution
7+
8+
9+
class TestReverseLinkedList:
10+
def setup_method(self):
11+
self.solution = Solution()
12+
13+
@pytest.mark.parametrize(
14+
"head_list, expected_list",
15+
[
16+
([1, 2, 3, 4, 5], [5, 4, 3, 2, 1]), # Basic case
17+
([1, 2], [2, 1]), # Two nodes
18+
([1], [1]), # Single node
19+
([], []), # Empty list
20+
([1, 2, 3], [3, 2, 1]), # Odd length
21+
([1, 2, 3, 4], [4, 3, 2, 1]), # Even length
22+
([-1, -2, -3], [-3, -2, -1]), # Negative values
23+
([0], [0]), # Zero value
24+
([5000, -5000], [-5000, 5000]), # Boundary values
25+
([1, 1, 1], [1, 1, 1]), # Duplicate values
26+
],
27+
)
28+
@logged_test
29+
def test_reverse_list(self, head_list: list[int], expected_list: list[int]):
30+
# Convert input list to linked list structure
31+
# e.g., [1,2,3] -> 1->2->3->None
32+
head = ListNode.from_list(head_list)
33+
34+
# Convert expected result list to linked list for comparison
35+
# e.g., [3,2,1] -> 3->2->1->None
36+
expected = ListNode.from_list(expected_list)
37+
38+
# Call the reverse_list method to reverse the linked list
39+
# This should transform 1->2->3->None into 3->2->1->None
40+
result = self.solution.reverse_list(head)
41+
42+
# Verify that the reversed linked list matches expected output
43+
# ListNode supports direct equality comparison
44+
assert result == expected

0 commit comments

Comments
 (0)