This exercise tests the your understanding of linked lists, recursion or iteration, and manipulation of pointers. It also evaluates your ability to write clean and efficient code.

Solution 1: Iterative

class ListNode:
    def __init__(self, value=0, next=None):
        self.value = value
        self.next = next

def reverse_linked_list(head: ListNode) -> ListNode:
    # Initialize three pointers to reverse the linked list
    prev = None
    current = head
    next_node = None

    # Traverse the linked list
    while current is not None:
        # Save the next node
        next_node = current.next

        # Reverse the link
        current.next = prev

        # Move to the next nodes
        prev = current
        current = next_node

    # The new head is the previous node after reversal
    head = prev

    return head

# Helper function to print the linked list
def print_linked_list(head: ListNode):
    current = head
    while current:
        print(current.value, end=" -> ")
        current = current.next
    print("None")

# Example usage:
# Create a sample linked list: 1 -> 2 -> 3 -> 4 -> 5
head = ListNode(1, ListNode(2, ListNode(3, ListNode(4, ListNode(5)))))
print("Original Linked List:")
print_linked_list(head)

# Reverse the linked list
head = reverse_linked_list(head)

# Print the reversed linked list: 5 -> 4 -> 3 -> 2 -> 1
print("\nReversed Linked List:")
print_linked_list(head)

This solution uses an iterative approach with three pointers to reverse the linked list in-place. It has a time complexity of O(n) and a space complexity of O(1), meeting the constraints of the problem.

Solution 2: Recursion

Below is a solution using recursion.

class ListNode:
    def __init__(self, value=0, next=None):
        self.value = value
        self.next = next

def reverse_linked_list(head: ListNode) -> ListNode:
    # Base case: an empty list or a list with a single node is already reversed
    if head is None or head.next is None:
        return head

    # Recursively reverse the rest of the linked list
    reversed_tail = head.next
    new_head = reverse_linked_list(head.next)

    # Reverse the links
    reversed_tail.next = head
    head.next = None

    return new_head

# Helper function to print the linked list
def print_linked_list(head: ListNode):
    current = head
    while current:
        print(current.value, end=" -> ")
        current = current.next
    print("None")

# Example usage:
# Create a sample linked list: 1 -> 2 -> 3 -> 4 -> 5
head = ListNode(1, ListNode(2, ListNode(3, ListNode(4, ListNode(5)))))
print("Original Linked List:")
print_linked_list(head)

# Reverse the linked list using recursion
head = reverse_linked_list(head)

# Print the reversed linked list: 5 -> 4 -> 3 -> 2 -> 1
print("\nReversed Linked List:")
print_linked_list(head)

This recursive solution also has a time complexity of O(n) and a space complexity of O(n) due to the recursive call stack. The base case ensures that the recursion stops when the end of the linked list is reached.