Problem overview
The method isPalindrome(_ input: String) -> Bool returns true when the string reads the same forwards and backwards. "madam racecar madam" is a palindrome, because reversing it, spaces included, gives the same text. "abcbx" is not, because its reverse is "xbcba".
The comparison is exact. Spaces count as characters, and uppercase and lowercase letters differ, so "Aa" is not a palindrome.
Approach: reverse, then compare
A palindrome equals its own reverse. That gives a very short solution: build the reversed string and test whether it is equal to the original. The comparison is a single expression, so there is no loop to write and no index to get wrong.
The statement's hints describe another approach, two pointers that start at both ends and move toward the middle, comparing one pair of characters at a time. It can stop at the first mismatch, so it compares fewer characters on strings that fail early. This lesson takes the shorter route with the reversal. Both approaches look at every character in the worst case, so both are linear in time, but the reversal builds a second string, which costs O(n) extra space. The two-pointer version is the one that fits the O(1) space note.
Step by step
- Reverse the input. Declare the constant
reversedInputasString(input.reversed()). The callreversed()returns the characters in reverse order, but as a collection and not as aString, so it is wrapped inString(...). - Compare and return.
input == reversedInputalready evaluates totrueorfalse, so the method returns it directly, with noif.
The solution in Swift
class Solution {
func isPalindrome(_ input: String) -> Bool {
let reversedInput = String(input.reversed())
return input == reversedInput
}
}
The Swift details worth a closer look:
- What
reversed()returns. On a string it gives aReversedCollection<String>, a lightweight view that walks the characters from the end. Passing it toString(...)copies those characters into a real string. That copy is theO(n)extra space. - Comparison by contents.
==on two strings compares their characters, not where they are stored. Swift also treats strings as equal when they are canonically equivalent, so"\u{E9}"(a single "é") equals"e\u{301}"("e" plus a combining accent). - Characters, not bytes. The reversal works on
Charactervalues. A letter with a combining accent stays in one piece, so a string such as"e\u{301}e\u{301}"is correctly judged a palindrome. - Returning a comparison. Writing
if input == reversedInput { return true } else { return false }works but only repeats what the expression already says.
Complexity
Time: O(n). Reversing visits each character once, and the comparison does at most n character checks.
Space: O(n). The reversed string is a second copy of the input. The note in the statement asks for O(1), which the two-pointer version reaches by working on the original string, or on an array of its characters, in place.
Edge cases and common mistakes
- Empty string. Its reverse is also empty, so the result is
true. - One character.
"a"is a palindrome. - Case.
"Aa"returnsfalse, because"A"and"a"are different characters. If a problem wants a case-insensitive answer, lowercase the input first withlowercased(). - Spaces and punctuation.
"A man"returnsfalse. Nothing is skipped; every character takes part in the comparison. - Forgetting
String(...).input == input.reversed()does not compile: the compiler cannot apply==to aStringand an array of characters, becausereversed()gives characters, not aString. - Even and odd lengths.
"abba"and"aba"both work with no special handling, which a two-pointer loop also gives you with the conditioni < j.
Testing
"madam racecar madam"givestrue."abcbx"givesfalse.""givestrue."abba"givestrue."ab"givesfalse."Aa"givesfalse.
