-
-
Notifications
You must be signed in to change notification settings - Fork 46.8k
Add DocTests to is_palindrome.py #10081
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
9c16d06
de9280c
1e9a24c
8e984f1
8923970
e92c9e6
dd72ef8
3808ddc
6b5629a
2299c0f
3206174
331ca32
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -1,65 +1,167 @@ | ||||||||||||||||||
def is_palindrome(head): | ||||||||||||||||||
from __future__ import annotations | ||||||||||||||||||
|
||||||||||||||||||
from dataclasses import dataclass | ||||||||||||||||||
|
||||||||||||||||||
|
||||||||||||||||||
@dataclass | ||||||||||||||||||
class ListNode: | ||||||||||||||||||
SaiHarshaK marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||
val: int = 0 | ||||||||||||||||||
next_node: ListNode | None = None | ||||||||||||||||||
|
||||||||||||||||||
|
||||||||||||||||||
def is_palindrome(head: ListNode | None) -> bool: | ||||||||||||||||||
""" | ||||||||||||||||||
Check if a linked list is a palindrome. | ||||||||||||||||||
|
||||||||||||||||||
Args: | ||||||||||||||||||
head: The head of the linked list. | ||||||||||||||||||
|
||||||||||||||||||
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 | ||||||||||||||||||
""" | ||||||||||||||||||
if not head: | ||||||||||||||||||
return True | ||||||||||||||||||
# split the list to two parts | ||||||||||||||||||
fast, slow = head.next, head | ||||||||||||||||||
while fast and fast.next: | ||||||||||||||||||
fast = fast.next.next | ||||||||||||||||||
slow = slow.next | ||||||||||||||||||
second = slow.next | ||||||||||||||||||
slow.next = None # Don't forget here! But forget still works! | ||||||||||||||||||
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 = None | ||||||||||||||||||
node: ListNode | None = None | ||||||||||||||||||
while second: | ||||||||||||||||||
nxt = second.next | ||||||||||||||||||
second.next = node | ||||||||||||||||||
nxt = second.next_node | ||||||||||||||||||
second.next_node = node | ||||||||||||||||||
node = second | ||||||||||||||||||
second = nxt | ||||||||||||||||||
# compare two parts | ||||||||||||||||||
# second part has the same or one less node | ||||||||||||||||||
while node: | ||||||||||||||||||
while node and head: | ||||||||||||||||||
if node.val != head.val: | ||||||||||||||||||
return False | ||||||||||||||||||
node = node.next | ||||||||||||||||||
head = head.next | ||||||||||||||||||
node = node.next_node | ||||||||||||||||||
head = head.next_node | ||||||||||||||||||
SaiHarshaK marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||
return True | ||||||||||||||||||
|
||||||||||||||||||
|
||||||||||||||||||
def is_palindrome_stack(head): | ||||||||||||||||||
if not head or not head.next: | ||||||||||||||||||
def is_palindrome_stack(head: ListNode | None) -> bool: | ||||||||||||||||||
""" | ||||||||||||||||||
Check if a linked list is a palindrome using a stack. | ||||||||||||||||||
|
||||||||||||||||||
Args: | ||||||||||||||||||
head (ListNode): The head of the linked list. | ||||||||||||||||||
|
||||||||||||||||||
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 | ||||||||||||||||||
""" | ||||||||||||||||||
if not head or not head.next_node: | ||||||||||||||||||
return True | ||||||||||||||||||
|
||||||||||||||||||
# 1. Get the midpoint (slow) | ||||||||||||||||||
slow = fast = cur = head | ||||||||||||||||||
while fast and fast.next: | ||||||||||||||||||
fast, slow = fast.next.next, slow.next | ||||||||||||||||||
|
||||||||||||||||||
# 2. Push the second half into the stack | ||||||||||||||||||
stack = [slow.val] | ||||||||||||||||||
while slow.next: | ||||||||||||||||||
slow = slow.next | ||||||||||||||||||
stack.append(slow.val) | ||||||||||||||||||
|
||||||||||||||||||
# 3. Comparison | ||||||||||||||||||
while stack: | ||||||||||||||||||
if stack.pop() != cur.val: | ||||||||||||||||||
return False | ||||||||||||||||||
cur = cur.next | ||||||||||||||||||
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): | ||||||||||||||||||
if not head or not head.next: | ||||||||||||||||||
def is_palindrome_dict(head: ListNode | None) -> bool: | ||||||||||||||||||
""" | ||||||||||||||||||
Check if a linked list is a palindrome using a dictionary. | ||||||||||||||||||
|
||||||||||||||||||
Args: | ||||||||||||||||||
head (ListNode): The head of the linked list. | ||||||||||||||||||
|
||||||||||||||||||
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))))))) | ||||||||||||||||||
Comment on lines
+150
to
+152
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. PEP8 discourages backslash line termination in Python because any whitespace to the right of the backslash breaks the script on a change that is invisible to the reader. Also, backslashes are not required inside of (), [], {}...
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ruff complains that the length of the line is >88 which is why I had to split them into multiple lines. If i do not add backslash, DocTest assumes There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You needed the three dots at the beginning of each continued line as discussed in the doctest docs. |
||||||||||||||||||
False | ||||||||||||||||||
""" | ||||||||||||||||||
if not head or not head.next_node: | ||||||||||||||||||
return True | ||||||||||||||||||
d = {} | ||||||||||||||||||
d: dict[int, list[int]] = {} | ||||||||||||||||||
pos = 0 | ||||||||||||||||||
while head: | ||||||||||||||||||
if head.val in d: | ||||||||||||||||||
d[head.val].append(pos) | ||||||||||||||||||
else: | ||||||||||||||||||
d[head.val] = [pos] | ||||||||||||||||||
head = head.next | ||||||||||||||||||
head = head.next_node | ||||||||||||||||||
pos += 1 | ||||||||||||||||||
checksum = pos - 1 | ||||||||||||||||||
middle = 0 | ||||||||||||||||||
|
@@ -75,3 +177,9 @@ def is_palindrome_dict(head): | |||||||||||||||||
if middle > 1: | ||||||||||||||||||
return False | ||||||||||||||||||
return True | ||||||||||||||||||
|
||||||||||||||||||
|
||||||||||||||||||
if __name__ == "__main__": | ||||||||||||||||||
import doctest | ||||||||||||||||||
|
||||||||||||||||||
doctest.testmod() |
Uh oh!
There was an error while loading. Please reload this page.