Skip to content

Conversation

@BrianLusina
Copy link
Owner

@BrianLusina BrianLusina commented Dec 19, 2025

Describe your change:

Reorder linked list by splitting it into two halves and then weaving and merging the two halves into one linked list

  • Add an algorithm?
  • Fix a bug or typo in an existing algorithm?
  • Documentation change?

Checklist:

  • I have read CONTRIBUTING.md.
  • This pull request is all my own work -- I have not plagiarized.
  • I know that pull requests will not be merged if they fail the automated tests.
  • This PR only changes one algorithm file. To ease review, please open separate PRs for separate algorithms.
  • All new Python files are placed inside an existing directory.
  • All filenames are in all lowercase characters with no spaces or dashes.
  • All functions and variable names follow Python naming conventions.
  • All function parameters and return values are annotated with Python type hints.
  • All functions have doctests that pass the automated testing.
  • All new algorithms have a URL in its comments that points to Wikipedia or other similar explanation.
  • If this pull request resolves one or more open issues then the commit message contains Fixes: #{$ISSUE_NO}.

Summary by CodeRabbit

  • New Features

    • Added linked list reversal functionality to LinkedList class.
    • Introduced singly linked list reordering method.
    • New utilities for merging and weaving linked lists.
  • Documentation

    • Added documentation section for Single Linked List utilities.
    • Added Reorder List documentation with examples and constraints.

✏️ Tip: You can customize this high-level summary in your review settings.

@BrianLusina BrianLusina self-assigned this Dec 19, 2025
@BrianLusina BrianLusina added enhancement Algorithm Algorithm Problem Datastructures Datastructures Documentation Documentation Updates Two Pointers Two pointer algorithm LinkedList Linked List Data Structure labels Dec 19, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 19, 2025

Walkthrough

This pull request introduces linked list manipulation utilities and features. It adds a reverse_list method to the LinkedList class, introduces a new reorder_list method to SinglyLinkedList, and provides two utility functions (merge_and_weave and reverse_list) for reordering operations. Documentation is updated, and comprehensive test coverage is added for all new functionality.

Changes

Cohort / File(s) Summary
Documentation Updates
DIRECTORY.md, datastructures/linked_lists/singly_linked_list/README.md
Added index entries for "Single Linked List Utils" and new "Reorder List" documentation section with problem description, examples, and constraints.
Linked List Core Implementation
datastructures/linked_lists/__init__.py
Added LinkedList.reverse_list(head) static method to reverse a linked list iteratively, returning the new head node.
Singly Linked List Implementation
datastructures/linked_lists/singly_linked_list/single_linked_list.py
Added SinglyLinkedList.reorder_list() method that splits the list into halves, reverses the second half, and weaves them together using new utility functions.
Singly Linked List Utilities
datastructures/linked_lists/singly_linked_list/single_linked_list_utils.py
Introduced two new public functions: reverse_list(head) to reverse a linked list in place and merge_and_weave(first_half_head, second_half_head) to interleave two linked lists.
Test Suite - New Tests
datastructures/linked_lists/singly_linked_list/test_singly_linked_list_reorder_list.py, test_singly_linked_merge_and_weave.py
Added parameterized test modules validating reorder_list() method and merge_and_weave() utility function with multiple input-output scenarios.
Test Suite - Updates
datastructures/linked_lists/singly_linked_list/test_singly_linked_revese.py
Added TEST_CASES global constant and two new test methods (test_reverse_linked_list(), test_reverse_linked_list_static()) to test the new standalone reverse_list() function and instance reversal method.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Areas requiring attention:

  • Logic correctness in reorder_list() method: verify list splitting, reversal, and weaving logic chain
  • merge_and_weave() utility: confirm pointer manipulation correctly interleaves nodes without data loss
  • reverse_list() implementations: ensure proper handling of edge cases (empty lists, single nodes, None inputs) across both static and instance method variants
  • Test coverage: validate parameterized test cases comprehensively exercise boundary conditions

Poem

🐰 A list once forward, now weaves to and fro,
Split, reversed, and merged with a magical flow!
These singly-linked threads we deftly entwine,
Each node finds its place in this new design. ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 68.75% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change—implementing a reorder list algorithm for linked lists. It is concise, specific, and directly related to the primary objective of the PR.
Description check ✅ Passed The PR description adequately follows the template structure with a clear explanation of changes. However, the last checklist item regarding 'Fixes: #{$ISSUE_NO}' is unchecked, which may indicate missing issue references if applicable.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/data-structures-linked-list-reorder-list

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (4)
datastructures/linked_lists/singly_linked_list/single_linked_list_utils.py (2)

23-23: Fix typo in comment.

"loose" should be "lose".

🔎 Proposed fix
-        # save the pointer 1 next node to not loose it
+        # save the pointer 1 next node to not lose it

65-65: Correct misleading comment.

The comment "return the new tail of the k-group which is our head" appears to be copied from a different context (reverse_groups). This function simply reverses the entire list and returns the new head.

🔎 Proposed fix
-    # return the new tail of the k-group which is our head
+    # return the new head of the reversed list
     return previous
DIRECTORY.md (1)

258-258: Address markdown list indentation.

The static analysis tool flags that these list items use 6-space indentation where 4 spaces are expected per the project's markdown style (MD007). While not critical, consistent formatting improves readability.

As per static analysis hints, consider adjusting indentation from 6 to 4 spaces to match the expected style.

Also applies to: 265-265, 267-267

datastructures/linked_lists/__init__.py (1)

719-750: Implementation is correct but duplicated.

This static utility correctly reverses a linked list. However, as noted in the review of single_linked_list_utils.py, this same logic exists in three places. Consider whether this static method should be the canonical implementation that other modules import, or if the utility module should be the source of truth.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fa51bf6 and fadd8c2.

⛔ Files ignored due to path filters (5)
  • datastructures/linked_lists/singly_linked_list/images/examples/singly_linked_list_reorder_list_example_1.png is excluded by !**/*.png
  • datastructures/linked_lists/singly_linked_list/images/examples/singly_linked_list_reorder_list_example_2.png is excluded by !**/*.png
  • datastructures/linked_lists/singly_linked_list/images/examples/singly_linked_list_reorder_list_example_3.png is excluded by !**/*.png
  • datastructures/linked_lists/singly_linked_list/images/examples/singly_linked_list_reorder_list_example_4.png is excluded by !**/*.png
  • datastructures/linked_lists/singly_linked_list/images/examples/singly_linked_list_reorder_list_example_5.png is excluded by !**/*.png
📒 Files selected for processing (8)
  • DIRECTORY.md (1 hunks)
  • datastructures/linked_lists/__init__.py (1 hunks)
  • datastructures/linked_lists/singly_linked_list/README.md (1 hunks)
  • datastructures/linked_lists/singly_linked_list/single_linked_list.py (2 hunks)
  • datastructures/linked_lists/singly_linked_list/single_linked_list_utils.py (1 hunks)
  • datastructures/linked_lists/singly_linked_list/test_singly_linked_list_reorder_list.py (1 hunks)
  • datastructures/linked_lists/singly_linked_list/test_singly_linked_merge_and_weave.py (1 hunks)
  • datastructures/linked_lists/singly_linked_list/test_singly_linked_revese.py (4 hunks)
🧰 Additional context used
🧬 Code graph analysis (5)
datastructures/linked_lists/__init__.py (3)
datastructures/linked_lists/singly_linked_list/single_linked_list.py (1)
  • reverse_list (908-928)
datastructures/linked_lists/singly_linked_list/single_linked_list_utils.py (1)
  • reverse_list (36-66)
datastructures/linked_lists/build_one_2_3/__init__.py (1)
  • Node (1-4)
datastructures/linked_lists/singly_linked_list/test_singly_linked_merge_and_weave.py (1)
datastructures/linked_lists/singly_linked_list/single_linked_list_utils.py (1)
  • merge_and_weave (5-33)
datastructures/linked_lists/singly_linked_list/test_singly_linked_revese.py (2)
datastructures/linked_lists/__init__.py (2)
  • reverse_list (720-750)
  • reverse (196-203)
datastructures/linked_lists/singly_linked_list/single_linked_list_utils.py (1)
  • reverse_list (36-66)
datastructures/linked_lists/singly_linked_list/single_linked_list.py (3)
datastructures/linked_lists/__init__.py (2)
  • reverse_list (720-750)
  • middle_node (671-687)
datastructures/linked_lists/singly_linked_list/single_linked_list_utils.py (2)
  • reverse_list (36-66)
  • merge_and_weave (5-33)
datastructures/linked_lists/singly_linked_list/node.py (1)
  • SingleNode (4-10)
datastructures/linked_lists/singly_linked_list/single_linked_list_utils.py (3)
datastructures/linked_lists/singly_linked_list/node.py (1)
  • SingleNode (4-10)
datastructures/linked_lists/__init__.py (1)
  • reverse_list (720-750)
datastructures/linked_lists/singly_linked_list/single_linked_list.py (1)
  • reverse_list (908-928)
🪛 markdownlint-cli2 (0.18.1)
DIRECTORY.md

258-258: Unordered list indentation
Expected: 4; Actual: 6

(MD007, ul-indent)


259-259: Unordered list indentation
Expected: 4; Actual: 6

(MD007, ul-indent)


260-260: Unordered list indentation
Expected: 4; Actual: 6

(MD007, ul-indent)


261-261: Unordered list indentation
Expected: 4; Actual: 6

(MD007, ul-indent)


262-262: Unordered list indentation
Expected: 4; Actual: 6

(MD007, ul-indent)


263-263: Unordered list indentation
Expected: 4; Actual: 6

(MD007, ul-indent)


264-264: Unordered list indentation
Expected: 4; Actual: 6

(MD007, ul-indent)


265-265: Unordered list indentation
Expected: 4; Actual: 6

(MD007, ul-indent)


266-266: Unordered list indentation
Expected: 4; Actual: 6

(MD007, ul-indent)


267-267: Unordered list indentation
Expected: 4; Actual: 6

(MD007, ul-indent)

🔇 Additional comments (8)
datastructures/linked_lists/singly_linked_list/test_singly_linked_list_reorder_list.py (1)

8-44: LGTM - comprehensive test coverage.

The test suite is well-structured with good coverage of various scenarios including:

  • Lists of different lengths (odd and even)
  • Lists with positive, negative, and mixed values
  • Edge cases like 3-node and 4-node lists

The test correctly builds the linked list, invokes reorder_list, and validates the reordered sequence by traversing the result.

datastructures/linked_lists/singly_linked_list/single_linked_list.py (2)

7-10: Imports look correct.

The imports of reverse_list and merge_and_weave from the utility module are appropriate for the new reorder_list implementation.


990-1019: Verify reorder_list logic flows correctly after fixing method call.

The overall algorithm is sound:

  1. Find the middle node
  2. Split into two halves
  3. Reverse the second half
  4. Merge/weave the halves

Once the critical issue on line 1013 is fixed, ensure the logic handles edge cases properly, especially for odd-length lists where the middle node stays in the first half.

datastructures/linked_lists/singly_linked_list/test_singly_linked_merge_and_weave.py (1)

11-49: LGTM - good test coverage for merge_and_weave utility.

The tests appropriately cover:

  • Empty input scenario (both lists empty)
  • Different length lists being merged
  • Correct interleaving/weaving of nodes

The test correctly constructs two linked lists, calls merge_and_weave, and validates the merged result by traversing and comparing to the expected sequence.

datastructures/linked_lists/singly_linked_list/test_singly_linked_revese.py (4)

7-9: Import addition is appropriate.

Adding the reverse_list utility import enables testing of the standalone function alongside the instance method.


11-34: Good refactoring to centralize test cases.

Moving test cases to a module-level TEST_CASES constant improves maintainability and makes it easier to reuse test data across multiple test methods.


42-44: Correct expectation for invalid input.

The change to expect ValueError when calling reverse_between(0, 1) on an empty list is correct, as reverse_between validates that left and right must be positive integers (≥ 1).


101-136: LGTM - comprehensive testing of reverse functionality.

The two new tests provide good coverage:

  • test_reverse_linked_list: validates the instance method .reverse()
  • test_reverse_linked_list_static: validates the standalone reverse_list utility function

Both correctly build a linked list, perform reversal, traverse the result, and assert the expected reversed sequence.

Comment on lines +16 to +17
if first_half_head is None or second_half_head is None:
return None
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

cd datastructures/linked_lists/singly_linked_list && find . -name "*.py" | head -20

Repository: BrianLusina/PythonSnips

Length of output: 611


🏁 Script executed:

cat -n datastructures/linked_lists/singly_linked_list/single_linked_list_utils.py | head -80

Repository: BrianLusina/PythonSnips

Length of output: 2483


🏁 Script executed:

# Also search for usage in single_linked_list.py
grep -n "merge_and_weave\|reorder" datastructures/linked_lists/singly_linked_list/single_linked_list.py | head -20

Repository: BrianLusina/PythonSnips

Length of output: 259


🏁 Script executed:

sed -n '985,1025p' datastructures/linked_lists/singly_linked_list/single_linked_list.py

Repository: BrianLusina/PythonSnips

Length of output: 1636


Fix early-return logic for edge cases in merge_and_weave.

The function returns None when either input is None. For single-node lists passed from reorder_list, this causes incorrect behavior—a single node should be returned unchanged, not None. Change lines 16-17 to return the non-None input:

if first_half_head is None:
    return second_half_head
if second_half_head is None:
    return first_half_head
🤖 Prompt for AI Agents
In datastructures/linked_lists/singly_linked_list/single_linked_list_utils.py
around lines 16 to 17, the early-return incorrectly returns None when one list
is missing; instead return the non-None head so single-node lists are preserved.
Replace the combined None-check with two checks: if first_half_head is None
return second_half_head; if second_half_head is None return first_half_head,
preserving the existing list when the other side is absent.

Comment on lines +36 to +66
def reverse_list(head: SingleNode) -> Optional[SingleNode]:
"""
Reverses a linked list given the head node
Args:
head Node: the head node of the linked list
Returns:
Optional[Node]: the new head node of the reversed linked list
"""
if head is None or head.next is None:
return head

# track previous node, so we can point our next pointer to it
previous = None
# track node to loop through
current_node = head

while current_node:
# track the next node to not lose it while adjusting pointers
nxt = current_node.next

# set the next pointer to the node behind it, previous
current_node.next = previous

# adjust the new previous node to the current node for subsequent loops
previous = current_node

# move our node pointer up to the next node in front of it
current_node = nxt

# return the new tail of the k-group which is our head
return previous
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Eliminate code duplication for reverse_list.

This reverse_list function duplicates the implementation in:

  • datastructures/linked_lists/__init__.py (lines 719-749)
  • datastructures/linked_lists/singly_linked_list/single_linked_list.py (lines 907-927, inline in reverse_groups)

Consider consolidating to a single canonical implementation (likely the static utility in __init__.py) and importing it where needed, rather than maintaining three identical copies.

Based on learnings, code duplication should be avoided to reduce maintenance burden and potential for divergence.

🤖 Prompt for AI Agents
datastructures/linked_lists/singly_linked_list/single_linked_list_utils.py lines
36-66: this reverse_list implementation is a duplicate; remove the local
function and instead import the canonical reverse_list from
datastructures.linked_lists (the static utility in __init__.py), update this
module to export or use that imported function, ensure Optional and SingleNode
types are imported/referenced consistently, and update any local calls to use
the imported function so there’s a single maintained implementation across the
codebase.

# The reversal step involves taking the second half of the linked list and reversing it in place
# for example, if the linked list is 1 -> 2 -> 3 -> 4 -> 5, the second half is 3 -> 4 -> 5
# after reversing, it becomes 5 -> 4 -> 3
reversed_second_half = self.reverse_list(second_half_head)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# First, find the file location
FILE_PATH=$(find . -name "single_linked_list.py" -type f 2>/dev/null | head -1)

if [ -z "$FILE_PATH" ]; then
    echo "File not found. Searching for variations..."
    find . -name "*linked_list*.py" -type f 2>/dev/null | grep -i single | head -5
else
    echo "Found file: $FILE_PATH"
    
    # Check line 8 for imports
    echo "=== Lines around line 8 (imports) ==="
    sed -n '1,20p' "$FILE_PATH"
    
    # Check line 1013
    echo ""
    echo "=== Line 1013 (the problematic line) ==="
    sed -n '1010,1016p' "$FILE_PATH"
    
    # Check if reverse_list is defined as a method in the class
    echo ""
    echo "=== Searching for reverse_list definitions ==="
    grep -n "def reverse_list" "$FILE_PATH"
    
    # Check for self.reverse_list calls
    echo ""
    echo "=== Checking for self.reverse_list calls ==="
    grep -n "self\.reverse_list" "$FILE_PATH"
fi

Repository: BrianLusina/PythonSnips

Length of output: 1556


Fix incorrect method call on line 1013.

self.reverse_list(second_half_head) attempts to call reverse_list as a class method, but reverse_list is imported as a standalone function (line 8), not a method of SinglyLinkedList. This will cause an AttributeError at runtime.

-        reversed_second_half = self.reverse_list(second_half_head)
+        reversed_second_half = reverse_list(second_half_head)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
reversed_second_half = self.reverse_list(second_half_head)
reversed_second_half = reverse_list(second_half_head)
🤖 Prompt for AI Agents
In datastructures/linked_lists/singly_linked_list/single_linked_list.py around
line 1013, the code calls self.reverse_list(second_half_head) but reverse_list
is imported as a standalone function (not a SinglyLinkedList method); replace
the method call with a call to the imported function
(reverse_list(second_half_head)) and ensure the top-level import for
reverse_list remains correct and used consistently in this file.

@BrianLusina BrianLusina merged commit 4d9387b into main Dec 20, 2025
5 of 6 checks passed
@BrianLusina BrianLusina deleted the feat/data-structures-linked-list-reorder-list branch December 20, 2025 06:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Algorithm Algorithm Problem Datastructures Datastructures Documentation Documentation Updates enhancement LinkedList Linked List Data Structure Two Pointers Two pointer algorithm

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants