Python 2074.py
class Solution:
def reverseEvenLengthGroups(self, head: Optional[ListNode]) -> Optional[ListNode]:
# flatten the list
flat = []
scan = head
while scan:
flat.append(scan.val)
scan = scan.next
# partial reversal
result = []
group = 1
while flat:
# last group might be shorter
group = min(group, len(flat))
if group & 1: # odd
result += flat[:group]
else: # even => reverse
result += flat[:group][::-1]
del flat[:group]
group += 1
# convert back to a list
pos = 0
scan = head
while scan:
scan.val = result[pos]
scan = scan.next
pos += 1
return head
Difficulty
and has an acceptance rate of about 65% (70k+ submissions).
Typical patterns to solve this problem:
- Linked List
AI Disclaimer
However, two years later I set up this website and used various AI tools to generate most of the walkthrough / explanations below.
See this dedicated page for more details.
Code Walkthrough
Overview
The provided implementation solves the problem of reversing nodes in even-length groups within a singly-linked list. It follows a three-phase strategy: flatten the linked structure into a Python list, process the list in groups while conditionally reversing even-sized groups, and finally write the transformed values back into the original linked nodes. The algorithm works in-place on the existing nodes, preserving the original list objects.
Flattening the List
The first phase extracts the values from the linked list into a plain Python list named flat.
flat = []
scan = head
while scan:
flat.append(scan.val)
scan = scan.next
By iterating with a temporary pointer scan, each node’s val is appended, producing a contiguous sequence that mirrors the original order. This representation enables random access and slice operations that are cumbersome on a linked list.
Group Processing with Conditional Reversal
The core logic iterates over flat, forming groups whose sizes increase incrementally (1, 2, 3, …). For each group the code decides whether to keep the order or reverse it based on the parity of the group size.
result = []
group = 1
while flat:
group = min(group, len(flat)) # handle final short group
if group & 1: # odd length - keep order
result += flat[:group]
else: # even length - reverse order
result += flat[:group][::-1]
del flat[:group] # remove processed elements
group += 1
Key points:
group = min(group, len(flat))guarantees that the last group, which may be shorter than the expected size, is processed correctly without overrunning the list.- The bitwise test
group & 1efficiently distinguishes odd from even group lengths. - Slicing
flat[:group]extracts the current segment, and[::-1]produces a reversed copy when needed. - After handling a segment,
del flat[:group]discards it, allowing the loop to progress without additional index bookkeeping.
Rebuilding the List
Having built result, which holds the final sequence of values, the algorithm walks the original linked list again, overwriting each node’s val with the corresponding entry from result.
pos = 0
scan = head
while scan:
scan.val = result[pos]
scan = scan.next
pos += 1
Because the node objects themselves are unchanged, any external references to the list remain valid, and only the payload values are updated.
Edge Cases Handled
The implementation gracefully manages several boundary conditions:
- An empty input (
headisNone) results inflatbeing empty; the subsequent loops are bypassed andNoneis returned unchanged. - A list whose total length is less than the size of the first group (i.e., a single-node list) is processed by the
min(group, len(flat))guard, ensuring the solitary element is copied directly. - When the final group is shorter than the expected size, the same guard truncates the group size to the remaining element count, preventing index errors and correctly applying the odd/even rule based on the actual group length.
- The algorithm does not rely on sentinel nodes or dummy heads, so it works uniformly regardless of the list’s head position.
Performance Optimizations
Several choices contribute to efficient execution:
- Converting the linked list to a flat Python list enables O(1) slice extraction and reversal, avoiding repeated traversal of the linked structure for each group.
- The use of
group & 1provides a fast parity check without invoking higher-level arithmetic. - In-place modification of node values eliminates the need to allocate new
ListNodeobjects, reducing memory churn and preserving reference integrity. - Deleting processed portions of
flatwithdel flat[:group]shrinks the list in place, keeping the remaining slice operations cheap as the list size diminishes over time.
Overall, the code leverages Python’s list operations to achieve a concise solution that runs efficiently for typical input sizes while handling all edge conditions correctly.
ELI5 - Simplified Explanation
Imagine a long train where each carriage holds a secret number. The train starts out in a line, but it is organized into groups. The first group has one carriage, the second group has two carriages, the third group has three carriages, and so on.
The first step is to take all the secret numbers out of the carriages and put them into a simple list so the numbers are easy to see. Once the numbers are in the list, the work of grouping begins.
A counter starts at one to keep track of how many carriages should be in each group. When looking at a group, the code checks if the number of carriages is an odd number or an even number. If the group has an odd number of carriages, the numbers stay in their current order. If the group has an even number of carriages, the code flips them around so the last becomes the first and the first becomes the last.
After processing a group, the counter gets bigger, which makes the next group a little bit longer. This continues until every carriage has been placed into its new spot in the result list.
Finally, the code goes back to the original train carriages and swaps the old numbers with the new ones from the result list, keeping them in the same order they were placed. The train is now reorganized based on the clever rules for even and odd groups.
Code Quality
Complexity Analysis
Other Solutions
Obviously, I did that after I solved the problem myself.
In general, AlgoMonster and WalkCCC solutions are high-quality and always worth a look.
I haven't checked most of the other solutions, but they might be helpful as well.
And of course, the LeetCode forum is always a good place (or even the best) to look for alternative approaches.
(click on a column header to sort the table)
| author | ||||||||
|---|---|---|---|---|---|---|---|---|
| author | solutions | |||||||
| www | AlgoMonster | C++ | Python | Java | TS | |||
| WalkCCC | C++ | Python | Java | |||||
| leetcode.ca | Python | Java | TS | |||||
| Progiez | C++ | Python | Java | |||||
| github | black-shadows | C++ | ||||||
| charles-wangkai | Java | |||||||
| everthis | JS | |||||||
| fartem | Ruby | |||||||
| fsq | C++ | |||||||
| JoshCrozier | JS | |||||||
| lkwq007 | Python | |||||||
| suxrobGM | C# | |||||||
| trung-hn | Python | |||||||
| varunu28 | Java | |||||||
| wisdompeak | C++ | |||||||
| AlgoMonster | C++, Python, Java, TypeScript | |||||||
| WalkCCC | C++, Python, Java | |||||||
| leetcode.ca | Java, Python, TypeScript | |||||||
| Progiez | C++, Java, Python | |||||||
| black-shadows | C++, C++ | |||||||
| charles-wangkai | Java | |||||||
| everthis | JavaScript | |||||||
| fartem | Ruby | |||||||
| fsq | C++ | |||||||
| JoshCrozier | JavaScript | |||||||
| lkwq007 | Python | |||||||
| suxrobGM | C# | |||||||
| trung-hn | Python | |||||||
| varunu28 | Java | |||||||
| wisdompeak | C++ |
Videos
Similar Problems
- problem 206: Reverse Linked List
Solved On The Same Day
- problem 1072: Flip Columns For Maximum Number of Equal Rows
- problem 2043: Simple Bank System
- problem 2091: Removing Minimum and Maximum From Array
- problem 2517: Maximum Tastiness of Candy Basket
Extra
- Tech Stack - my development environment and tools
- AI - how AI helped me create this website (NOT solving the problems)
- Progress - progression over time
- Quality - code quality