-
Notifications
You must be signed in to change notification settings - Fork 4.7k
Expand file tree
/
Copy pathis_palindrome.py
More file actions
152 lines (112 loc) · 3.62 KB
/
is_palindrome.py
File metadata and controls
152 lines (112 loc) · 3.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
"""
Is Palindrome
Determine if a string is a palindrome, considering only alphanumeric
characters and ignoring cases. Multiple approaches are provided.
Reference: https://en.wikipedia.org/wiki/Palindrome
Complexity:
Time: O(n) for all variations
Space: O(n) for variations that create new strings, O(1) for two-pointer
"""
from __future__ import annotations
from collections import deque
from string import ascii_letters
def is_palindrome(text: str) -> bool:
"""Check if a string is a palindrome using two pointers on the original.
Args:
text: The input string to check.
Returns:
True if the string is a palindrome, False otherwise.
Examples:
>>> is_palindrome("Otto")
True
"""
left = 0
right = len(text) - 1
while left < right:
while not text[left].isalnum():
left += 1
while not text[right].isalnum():
right -= 1
if text[left].lower() != text[right].lower():
return False
left, right = left + 1, right - 1
return True
def _remove_punctuation(text: str) -> str:
"""Remove punctuation, case sensitivity and spaces from a string.
Args:
text: The input string to clean.
Returns:
A lowercase string with only alphabetic characters.
"""
return "".join(char.lower() for char in text if char in ascii_letters)
def _string_reverse(text: str) -> str:
"""Reverse a string using slicing.
Args:
text: The string to reverse.
Returns:
The reversed string.
"""
return text[::-1]
def is_palindrome_reverse(text: str) -> bool:
"""Check if a string is a palindrome by comparing with its reverse.
Args:
text: The input string to check.
Returns:
True if the string is a palindrome, False otherwise.
Examples:
>>> is_palindrome_reverse("Otto")
True
"""
text = _remove_punctuation(text)
return text == _string_reverse(text)
def is_palindrome_two_pointer(text: str) -> bool:
"""Check if a string is a palindrome using two pointers from both ends.
Args:
text: The input string to check.
Returns:
True if the string is a palindrome, False otherwise.
Examples:
>>> is_palindrome_two_pointer("Otto")
True
"""
text = _remove_punctuation(text)
for index in range(0, len(text) // 2):
if text[index] != text[len(text) - index - 1]:
return False
return True
def is_palindrome_stack(text: str) -> bool:
"""Check if a string is a palindrome using a stack.
Args:
text: The input string to check.
Returns:
True if the string is a palindrome, False otherwise.
Examples:
>>> is_palindrome_stack("Otto")
True
"""
stack: list[str] = []
text = _remove_punctuation(text)
for index in range(len(text) // 2, len(text)):
stack.append(text[index])
return all(text[index] == stack.pop() for index in range(0, len(text) // 2))
def is_palindrome_deque(text: str) -> bool:
"""Check if a string is a palindrome using a deque.
Args:
text: The input string to check.
Returns:
True if the string is a palindrome, False otherwise.
Examples:
>>> is_palindrome_deque("Otto")
True
"""
text = _remove_punctuation(text)
character_deque: deque[str] = deque()
for char in text:
character_deque.appendleft(char)
equal = True
while len(character_deque) > 1 and equal:
first = character_deque.pop()
last = character_deque.popleft()
if first != last:
equal = False
return equal