In this article
Before you start
Why interviewers ask this
Reversing a string is one of the shortest problems an interviewer can set, and that is the reason it is used: the answer takes a minute, so the rest of the time shows how you think. A candidate who types the one-line slice and stops shows that they know a language feature. A candidate who also says what the slice costs, writes the in-place version when asked, and names the case where "reverse" is ill-defined shows that they reason about memory, loops and input.
The problem is common as a first question in a screening call and as a warm-up before a harder one, for example the sliding window problem on repeated characters. It is reported in interviews at large tech companies and in phone screens. Weak answers stop at the code. Strong answers state the complexity, handle the edge cases (an empty string, one character, a palindrome) and ask whether the input is a string or an array of characters, which changes the whole problem. The sections below teach each of those from zero.
Reversing a string from first principles
- Two pointers
- Two pointers is a technique that keeps two index variables into one sequence and moves them by a rule, either toward each other from the ends or in the same direction at different speeds, so one pass replaces a nested loop; for reversal they meet in the middle, each covering half.
- In place
- In place is a way of running an algorithm that changes the input directly and uses only a constant amount of extra memory, however long the input is, instead of building a second copy.
- Surrogate pair
- A surrogate pair is a pair of 16-bit UTF-16 code units that together encode one character outside the Basic Multilingual Plane (above U+FFFF (hexadecimal FFFF, which is 65,535 in decimal)), where UTF-16 is the encoding that stores text as 16-bit code units; Java stores characters above U+FFFF, which its documentation calls supplementary characters, as a pair of
charvalues from the high-surrogate and low-surrogate ranges (Oracle, Java Standard Edition (SE) 21 Javadoc, Character, read October 2026), so a character such as the G clef U+1D11E takes two of them.1 - Code point
- A code point is a number that the Unicode standard assigns to one character or mark, written like U+0301; Python counts the length of a string in code points, and one visible symbol can need several of them (Python documentation, str, read October 2026).
In plain words
Think of a row of cards laid face up on a table. To reverse the row, you can lay out a second row in the opposite order, copying each card. Or you can work in place: touch the first and last card, swap them, then the second and second-last, and stop when your hands meet in the middle.
The analogy breaks in one place. A card is one object, so swapping always moves one whole thing. A string character is not always one object: a letter and its accent mark can be two items that belong together. In one precise sentence: reversing a string means producing the sequence of its characters from last to first, either as a copy or by swapping pairs in place.
Step 1: Copy with a slice or a reverse iterator
The shortest solution builds a new string. The input is the string. In Python, the slice s[::-1] takes every item with a step of minus one, so it walks from the end to the start (Python documentation, slices, read October 2026). The built-in reversed(s) does the same walk as an iterator (an object that hands out the items one at a time), and "".join(reversed(s)) collects it (Python documentation, reversed, read October 2026).
The output is a new string, desserts for the input stressed.1 The input is not changed, and that is forced: Python strings are immutable, which means a string object cannot be altered after it is created, so any reversal must build a copy. The cost is time proportional to the length, written O(n), and extra memory proportional to the length. What you now know: this is the right answer when clarity matters and memory does not.
Step 2: Swap the ends with two pointers
The in-place version needs a mutable sequence. The input is an array (a list in Python) of characters. Put one pointer, i, at index 0 and another, j, at the last index. Swap the two characters, move i up by one and j down by one, and repeat.
On the array of stressed, the first swap exchanges the first character s and the last character d, giving dtresses.1 The loop condition is i < j. Each swap puts two characters in their final places, so after the first swap the outer pair is finished and never touched again. Nothing is allocated except two integers, so the extra memory is constant, written O(1). In Python a list also has reverse(), which reverses in place and returns None to remind you it works by side effect (a change to existing data rather than a returned value) (Python documentation, mutable sequence types, read October 2026).
Step 3: Stop at the middle
The loop stops when the pointers meet or cross, which is after half the length in swaps. For stressed, eight characters, that is four swaps: dtresses, deressts, desesrts, desserts.1 For a string of odd length, the middle character has no partner and stays where it is, so the loop never needs to swap it with itself.
The count is why the time is O(n): the loop runs n divided by 2 times, and constants are dropped in Big-O. A common bug is looping to the full length, which swaps every pair twice and returns the original string. Another is writing i <= j, which is harmless for one character but wastes a self-swap. The edge cases fall out of the condition. An empty string and a one-character string both skip the loop, and a palindrome such as level reverses to itself, which a test can use as a check. What you now know: the stopping rule is the whole algorithm.
Step 4: Check what a character is
In Python both versions reverse code points, and a visible symbol is not always one code point. A grapheme cluster is a user-perceived character: Unicode describes it as a base character followed by continuing characters such as combining marks (Unicode Standard Annex 29, revision 49, read October 2026). Take "café" written with a separate accent: five code points, c, a, f, e and U+0301.1 Reversed, the accent comes first and has no letter before it, so the e loses its accent and the mark is left on its own.
The same happens with the family emoji built from three people joined by U+200D, the zero width joiner (a code point that joins neighbours into one symbol): five code points, reversed.1 In Java and JavaScript the two-pointer swap on a char array splits characters above U+FFFF, while Java's StringBuilder.reverse keeps surrogate pairs (Oracle, Java SE 21 Javadoc, StringBuilder, read October 2026); a JavaScript run left lone surrogates.1 Neither knows about grapheme clusters. To reverse by user-perceived character, split into clusters with a segmentation library, reverse that list, then join.
Step-by-step description
- A slice builds a new string, so the input stays unchanged.
- Two pointers start at both ends and swap their characters.
- Pointers move inward and stop after four swaps.
- A combining accent must stay behind its letter.
- The slice with a step of minus one walks from the end to the start and gives desserts for stressed.
- The first swap exchanges the first character and the last character, giving dtresses.
- The loop stops after four swaps, when the two pointers meet.
- A combining accent reversed to the front has no letter before it and is detached from its e.
Knowing it is half the job. Saying it is the other half.
Interview Clozo is an AI interview copilot for real interview rounds: it hears the question and puts a strong answer on your screen, and you say it in your own words. See the features or how it works.
Start Free Trial →Worked example
Reverse stressed by hand with two pointers. The array has indices 0 to 7. Swap 0 and 7 to get dtresses, swap 1 and 6 to get deressts, swap 2 and 5 to get desesrts, swap 3 and 4 to get desserts. Then i is 4 and j is 3, so i < j is false and the loop ends. The program gave the same answer as the slice stressed[::-1], which is a good test to write.1
The next example shows why a mistake that looks harmless is expensive. A beginner writes result = ch + result for each character. Each step builds a new string, because strings are immutable, so the total number of characters copied is 1 + 2 + ... + n, which is n(n+1)/2. Counting it directly gave 36 copies for 8 characters and 500,500 for 1,000 characters.1
| String length n | Swaps with two pointers (n / 2) | Characters copied by prepending |
|---|---|---|
| 8 | 4 | 36 |
| 1,000 | 500 | 500,500 |
| 10,000 | 5,000 | 50,005,000 |
| 100,000 | 50,000 | 5,000,050,000 |
The first column of work grows in a straight line and the second grows with the square of n. Doubling the length from 1,000 to 2,000 raised the prepend count from 500,500 to 2,001,000, and 4,000 gave 8,002,000, about four times more per doubling.1 A real interpreter may optimise some string concatenations, so do not quote the table as a timing; it counts characters copied by the rule above.
Text description of the diagram
- Prepending to reverse 1,000 characters copies 500,500 characters in total.
- Prepending to reverse 4,000 characters copies 8,002,000 characters in total.
Trade-offs and edge cases
The choice among the three methods is about clarity, memory and what the input allows. The table lists the cost of each as derived in the steps above.
| Method | Time | Extra space | Mutates input |
|---|---|---|---|
Slice s[::-1] | O(n) | O(n) | No |
"".join(reversed(s)) | O(n) | O(n) | No |
| Two pointers on a list | O(n) | O(1) | Yes |
| Prepend in a loop | O(n squared) | O(n) | No |
If the input is a Python string, the two-pointer version first needs a list, which costs O(n) to build, so the "in place" claim holds only when the input is already an array of characters. That is the version many online judges (an online judge is a website that runs your code against hidden tests) use: a function that receives a list of characters and must change it directly. State that distinction aloud. Where the language has an immutable string and the problem says "in place", ask what the input type is before writing code.
The second edge case is Unicode, covered in step 4. Reported practice differs on how far to go: most interviews accept reversing code points and a spoken note about combining marks, while a production text tool should segment by grapheme cluster. A third case is reversing words instead of characters, which is a different problem: split on spaces, reverse the list of words, join, or reverse the whole string and then reverse each word back.
Text description of the diagram
- Slicing and reversed copy the string in linear time and linear space.
- Two pointers on a mutable array reverse in linear time with constant extra space.
- Prepending to the result in a loop copies a growing string each time.
How to answer it in an interview
Ask what the input is, give the simple version, then the in-place version and its cost, and end with the Unicode caveat. The answer below shows the shape; it is an illustrative example, not a script.
Write a function that reverses a string. What does it cost?
First I would ask whether I get a string or an array of characters. For a string in Python I would return the slice with a step of minus one, which copies the characters in linear time and linear space. If the problem asks for in place on an array, I use two pointers, one at each end, swap, and move inward until they meet, which is half the length in swaps, linear time and constant extra space. I would test an empty string, one character and a palindrome. I would also mention that in Python this reverses code points, so a letter with a combining accent would need grapheme clusters.
The spoken structure is: ask about the input, give the simple version, give the in-place version with its cost, test the edges, then name the Unicode limit. It takes about 45 seconds.
Common mistakes
- Looping over the whole length. (wrong) "I loop i from 0 to n and swap with n - 1 - i." (right) "I stop at the middle, because each swap fixes two characters; going further undoes the work."
- Claiming in place for an immutable string. (wrong) "I reverse the Python string in place." (right) "Python strings are immutable, so I build a copy, or convert to a list and reverse that."
- Prepending in a loop. (wrong) "I add each character to the front of a result string." (right) "That copies a growing string every time and is quadratic; I use a slice, a join over a reversed iterator, or swaps."
- Forgetting the edges. (wrong) "It works on my example." (right) "I also tried an empty string, one character and a palindrome."
- Ignoring what a character is. (wrong) "Every character is one position." (right) "A symbol can be several code points; I reverse code points and say so, or split by grapheme cluster."
Follow-up questions
How do you reverse a string in Java?
Java strings are immutable too, so the shortest answer is new StringBuilder(s).reverse().toString(), which the Javadoc documents as treating a surrogate pair as one character (Oracle, Java SE 21 Javadoc, read October 2026). The in-place answer is s.toCharArray() and two pointers, which is O(n) time and O(n) space for the array copy, and which splits characters above U+FFFF into their two char values, because the Java platform stores each of them as a surrogate pair (Oracle, Java SE 21 Javadoc, Character, read October 2026). Why strings cannot be changed in place in Python is the same reason: a string object cannot be altered after creation (Python documentation, str, read October 2026); convert to a list, reverse it and join.
Can you reverse a string with recursion?
Yes: the reverse of a string is the reverse of everything after the first character, followed by that first character. It makes n nested calls and copies characters in every slice and concatenation, about n squared in total (250,000 characters copied for 500 characters), and CPython's default recursion limit is 1000, so a string of 1,000 characters raised RecursionError in a run.1 (Python documentation, sys.getrecursionlimit, read October 2026). Say that a loop is the better answer.
What is the time and space complexity of reversing a string?
Time is O(n) for every sensible method, because each character is handled once or half of them are swapped. Space is O(n) for a copy and O(1) for two pointers on an array. Prepending in a loop is O(n squared) in characters copied.1
How do you reverse the words in a sentence instead of the characters?
Split the sentence into words, reverse the list of words and join them with spaces. It is a different problem from character reversal and it shares the same list reversal, and for a stack-based ordering problem see the monotonic stack walk-through.
How do you check whether a string is a palindrome?
Compare the string with its reverse, or use two pointers from the ends and stop at the first mismatch, which needs no copy. The word level equals its reverse.1
What changes if the input is an array of characters?
The in-place version becomes valid, because the array is mutable. You swap pairs with two pointers and return nothing, since the caller sees the change. For another problem that walks pointers through a structure, see the lowest common ancestor problem; for lookups, see hash-based sets and maps; and the machine learning coding round reuses these loops.
- Reversing a string is a copy (slice or reversed iterator, O(n) space) or an in-place swap loop (two pointers, O(1) space).
- Two pointers stop at the middle, after half the length in swaps.
- Prepending to a result in a loop copies a growing string each time and is quadratic.
- A character can be several code points, so reversing code points can detach an accent from its letter.
Sources
- Built-in types: common sequence operations, slices and str (Python 3 documentation) — Python Software Foundation (page shows a version, not a date; date = read date), 24 Oct 2026
- Built-in functions: reversed (Python 3 documentation) — Python Software Foundation (date = read date), 24 Oct 2026
- StringBuilder.reverse (Java SE 21 API documentation) — Oracle (date = read date), 24 Oct 2026
- Character (Java SE 21 API documentation), Unicode Character Representations — Oracle (date = read date), 24 Oct 2026
- sys.getrecursionlimit (Python 3 documentation) — Python Software Foundation (date = read date), 24 Oct 2026
- Unicode Standard Annex 29: Unicode Text Segmentation, revision 49 — Unicode Consortium, 1 Sep 2026