Medium · two pointers

Palindrome String

You already reversed a string by walking it backwards. Now walk it from both ends at once — and stop at the first mismatch, because one counterexample settles it.

At a glanceWalk two indices inward from both ends and print yes if they never disagree — the word is lowercase with no spaces, so no normalisation is needed.

Problem

Input: One line containing a single word of lowercase letters, at most 100 characters, with no spaces.

Output: yes if the word reads the same in both directions, otherwise no.

Samples:

InputOutput
racecaryes
hellono
ayes

A single character is trivially a palindrome, and so is an empty comparison. That's why the loop condition matters more than the loop body here.

Your solution

main.cpp — your solution
Custom input for "Run my input"

Judging runs in your browser against hidden tests. A runaway loop is cut off after 3 seconds — still, make sure every loop has an exit. Your code is saved in this browser as you type.

Stuck? Hints

Hint 1 — The naive version is two passes; you only need one

You could copy the string, reverse it, and compare — that's O(n) time and O(n) extra memory. But a palindrome is symmetric, so you can check it in place: character 0 against character n−1, then 1 against n−2, and so on. No copy needed.

Hint 2 — Two indices, one condition

int i = 0, j = n - 1; then while (i < j). Compare s[i] with s[j]; on a mismatch set a flag and break; otherwise i++ and j--. The i < j condition is what makes odd-length words work — the middle character compares against itself and would always pass anyway.

Hint 3 — The off-by-one that bites

The mirror of index i is n - 1 - i, not n - i. Write it wrong and you compare each character with its right-hand neighbour — plus you read one byte past the end of the string, which happens to be the terminator '\0', so the answer silently becomes wrong instead of crashing.

Solution (try it first!)
#include <iostream>
#include <cstring>
using namespace std;

int main() {
    char s[105];
    cin >> s;
    int n = strlen(s);

    int i = 0, j = n - 1;
    bool ok = true;
    while (i < j) {
        if (s[i] != s[j]) {
            ok = false;
            break;
        }
        i++;
        j--;
    }

    if (ok) cout << "yes" << endl;
    else cout << "no" << endl;
    return 0;
}

Two indices closing in on each other is the pattern behind a surprising amount: checking whether an array is sorted, removing duplicates in place, finding a pair that sums to a target in a sorted array, and the partition step of quicksort. The reason it works is always the same — the data has a symmetry, and two pointers let you exploit it without extra memory. Next, apply the same "read the shape, not the order" idea to a grid: Matrix Transpose.

Deep dive

Why this works

Two indices walk towards each other and each step compares one mirrored pair. The string has a symmetry; two pointers are how you spend it without copying anything.

The cost

O(n) time, O(1) space — and it stops at the first mismatch. Copying the string, reversing it and comparing is also O(n) time but needs O(n) extra memory for a copy you never wanted.

Where it goes wrong

  • Writing the mirror as n - i instead of n - 1 - i compares each character with its right-hand neighbour, and reads one byte past the end — which happens to be the '\0' terminator, so the answer silently goes wrong instead of crashing.
  • Using i <= j is harmless but pointless: the middle character ends up compared with itself. Using i < n is worse — it compares every pair twice.

Next step

Same idea, different shape — read a grid's structure instead of its order: Matrix Transpose.

Two things to remember

  • Two indices closing in, one mirrored pair per step.
  • The mirror of i is n - 1 - i, not n - i.
🐞 This version fails — open it and try

Mirror written as n - i — compares each character with its right neighbour

#include <iostream>
#include <cstring>
using namespace std;

int main() {
    char s[105];
    cin >> s;
    int n = strlen(s);
    bool ok = true;
    for (int i = 0; i < n / 2; i++) {
        if (s[i] != s[n - i]) ok = false;
    }
    if (ok) cout << "yes" << endl;
    else cout << "no" << endl;
    return 0;
}