Frontend
easy
mid
Write a function to check if a string is a palindrome without using the reverse string logic.
Use the two-pointer technique: one pointer from each end moving inward, comparing characters. O(n) time, O(1) space — no reversal, no extra allocation. Clarify whether to normalize case/whitespace/punctuation first.
4 min read·~10 min to think through
The constraint "without reversing" is pushing you toward the two-pointer technique — which is actually the better solution anyway (no extra allocation).
Two-pointer approach
js
function isPalindrome(str) {
let left = 0;
let right = str.length - 1;
while (left < right) {
if (str[left] !== str[right]) return false;
left++;
right--;
}
return true;
}- Compare the outermost pair, move inward. First mismatch → not a palindrome.
- Loop ends when the pointers meet (odd length: middle char ignored, correctly).
- O(n) time (really n/2 comparisons), O(1) space — beats the reverse-and-compare approach which allocates a whole new string.
Clarify the requirements first
Always ask: "raw characters, or normalized?" Common variant — ignore case, spaces, and punctuation ("A man, a plan, a canal: Panama"):
js
function isPalindrome(str) {
const s = str.toLowerCase().replace(/[^a-z0-9]/g, "");
let left = 0, right = s.length - 1;
while (left < right) {
if (s[left++] !== s[right--]) return false;
}
return true;
}Recursive variant (if they ask)
js
const isPal = (s, l = 0, r = s.length - 1) =>
l >= r ? true : s[l] !== s[r] ? false : isPal(s, l + 1, r - 1);Same O(n) time but O(n) call stack — worse than the loop for large inputs.
Edge cases
- Empty string / single char →
true(vacuously a palindrome). - Unicode —
str[i]indexes UTF-16 code units, so emoji/surrogate pairs break it; use[...str]to split into code points if Unicode matters. - Whitespace/case — depends entirely on the spec; ask.
What interviewers want
Reach for two pointers immediately, state O(n)/O(1), and ask the normalization question before coding — that clarification is itself a signal.
Follow-up questions
- •Why is two-pointer better than reverse-and-compare?
- •How would you handle the 'ignore punctuation and case' variant?
- •What's the tradeoff of the recursive version?
- •How does this break on emoji / Unicode, and how do you fix it?
Common mistakes
- •Reversing the string anyway (the prompt explicitly forbids it) — and allocating extra memory.
- •Not clarifying whether to normalize case/whitespace/punctuation.
- •Off-by-one in the pointer loop condition.
- •Indexing with [i] and breaking on surrogate pairs.
Performance considerations
- •Two-pointer is O(n) time, O(1) space — strictly better than building a reversed string (O(n) extra space). Recursion is O(n) time but O(n) stack.
Edge cases
- •Empty string and single character → true.
- •Mixed case / punctuation when normalization is expected.
- •Unicode characters and emoji.
- •Strings with only whitespace.
Real-world examples
- •Input validation, simple string-symmetry checks, a warm-up before harder palindrome problems (longest palindromic substring).
Senior engineer discussion
Seniors go straight to two pointers, state O(n)/O(1), and proactively ask the normalization question before writing code. They mention the Unicode indexing pitfall and note that the recursive form trades O(1) space for O(n) stack.
Related questions
Frontend
Easy
4 min
Frontend
Easy
4 min