Two-pointer on strings
Use two pointers moving inward from both ends, understand palindrome checking as the canonical example, and contrast with sliding window.
- Describe the two-pointer pattern (left at start, right at end, move inward)
- Recognise palindrome checking and reverse-words as canonical examples
- Contrast two-pointer (opposite ends) with sliding window (same direction)
A two-pointer technique places one pointer at the left end of a sequence and one at the right end, then moves them toward each other. The loop runs until the pointers meet or cross. Because each pointer travels at most n steps, the whole traversal is O(n) with O(1) extra space.
Palindrome check — the canonical example
A string is a palindrome if it reads the same forwards and backwards. Compare
the characters at left and right; if they match, move both inward. If any
pair mismatches, it is not a palindrome.
def is_palindrome(s):
left, right = 0, len(s) - 1
while left < right:
if s[left] != s[right]:
return False
left += 1
right -= 1
return TrueThe real-world version is trickier: "A man, a plan, a canal: Panama" is a palindrome if you ignore spaces, punctuation, and case. Filter to alphanumeric characters and lowercase before comparing:
def is_palindrome_clean(s):
chars = [c.lower() for c in s if c.isalnum()]
left, right = 0, len(chars) - 1
while left < right:
if chars[left] != chars[right]:
return False
left += 1
right -= 1
return TrueReversing words in place
Two-pointer works on word boundaries too. To reverse a list of words in place:
- Reverse the whole list with two pointers.
- Each word is now in the right position but its characters are reversed — run a second two-pointer pass on each word to un-reverse them.
def reverse_words(words):
left, right = 0, len(words) - 1
while left < right:
words[left], words[right] = words[right], words[left]
left += 1
right -= 1
return words
# ["hello", "world"] → ["world", "hello"]Two-pointer vs sliding window
Both patterns use two indices into the same array, which is why they are sometimes conflated. The distinction is in the direction of travel:
| Pattern | Direction | Typical goal |
|---|---|---|
| Sliding window | Both pointers left → right | Longest/shortest subarray satisfying a condition |
| Two-pointer (opposite ends) | Pointers shrink toward centre | Symmetry checks, pair-sum problems, reversals |
Sliding window can be thought of as a two-pointer variant where the right pointer leads and the left pointer follows, both moving right. The classic "two-pointer" label usually implies one pointer starts at the left end and the other at the right end, moving inward. The boundary is informal — the key is understanding which pointer moves in which direction and why.
Where to go next
Next: hashing strings — use character frequency maps (via Counter and
defaultdict) to check anagrams, group words, and understand the O(n) cost
of Python string hashing.