#### Is Palindrome

M
p
P
```from __future__ import annotations

from dataclasses import dataclass

@dataclass
class ListNode:
val: int = 0
next_node: ListNode | None = None

def is_palindrome(head: ListNode | None) -> bool:
"""
Check if a linked list is a palindrome.

Args:

Returns:
bool: True if the linked list is a palindrome, False otherwise.

Examples:
>>> is_palindrome(None)
True

>>> is_palindrome(ListNode(1))
True

>>> is_palindrome(ListNode(1, ListNode(2)))
False

>>> is_palindrome(ListNode(1, ListNode(2, ListNode(1))))
True

>>> is_palindrome(ListNode(1, ListNode(2, ListNode(2, ListNode(1)))))
True
"""
return True
# split the list to two parts
fast: ListNode | None = head.next_node
slow: ListNode | None = head
while fast and fast.next_node:
fast = fast.next_node.next_node
slow = slow.next_node if slow else None
if slow:
# slow will always be defined,
# adding this check to resolve mypy static check
second = slow.next_node
slow.next_node = None  # Don't forget here! But forget still works!
# reverse the second part
node: ListNode | None = None
while second:
nxt = second.next_node
second.next_node = node
node = second
second = nxt
# compare two parts
# second part has the same or one less node
return False
node = node.next_node
return True

def is_palindrome_stack(head: ListNode | None) -> bool:
"""
Check if a linked list is a palindrome using a stack.

Args:

Returns:
bool: True if the linked list is a palindrome, False otherwise.

Examples:
>>> is_palindrome_stack(None)
True

>>> is_palindrome_stack(ListNode(1))
True

>>> is_palindrome_stack(ListNode(1, ListNode(2)))
False

>>> is_palindrome_stack(ListNode(1, ListNode(2, ListNode(1))))
True

>>> is_palindrome_stack(ListNode(1, ListNode(2, ListNode(2, ListNode(1)))))
True
"""
return True

# 1. Get the midpoint (slow)
slow: ListNode | None = head
fast: ListNode | None = head
while fast and fast.next_node:
fast = fast.next_node.next_node
slow = slow.next_node if slow else None

# slow will always be defined,
# adding this check to resolve mypy static check
if slow:
stack = [slow.val]

# 2. Push the second half into the stack
while slow.next_node:
slow = slow.next_node
stack.append(slow.val)

# 3. Comparison
cur: ListNode | None = head
while stack and cur:
if stack.pop() != cur.val:
return False
cur = cur.next_node

return True

def is_palindrome_dict(head: ListNode | None) -> bool:
"""
Check if a linked list is a palindrome using a dictionary.

Args:

Returns:
bool: True if the linked list is a palindrome, False otherwise.

Examples:
>>> is_palindrome_dict(None)
True

>>> is_palindrome_dict(ListNode(1))
True

>>> is_palindrome_dict(ListNode(1, ListNode(2)))
False

>>> is_palindrome_dict(ListNode(1, ListNode(2, ListNode(1))))
True

>>> is_palindrome_dict(ListNode(1, ListNode(2, ListNode(2, ListNode(1)))))
True

>>> is_palindrome_dict(
...     ListNode(
...         1, ListNode(2, ListNode(1, ListNode(3, ListNode(2, ListNode(1)))))
...     )
... )
False
"""
return True
d: dict[int, list[int]] = {}
pos = 0
else:
pos += 1
checksum = pos - 1
middle = 0
for v in d.values():
if len(v) % 2 != 0:
middle += 1
else:
for step, i in enumerate(range(len(v))):
if v[i] + v[len(v) - 1 - step] != checksum:
return False
if middle > 1:
return False
return True

if __name__ == "__main__":
import doctest

doctest.testmod()
```