Definition
- Two-pointer reversal – place
leftat index 0 andrightat the last index of achar[]; swap and step inward. - Immutability workaround – Java strings are immutable, so convert to
char[]first, reverse, then build a newString. - Loop condition –
while (left < right)handles both odd and even lengths without special casing. - O(n) time – each character is swapped at most once.
- Space – O(n) for the
char[]and the new String, dictated by immutability, not the algorithm.
The National Bank of India prints a reference code backward on a receipt for a simple checksum. Think of the characters laid out in a row of boxes. One finger at the far left and one at the far right swap their contents, then both step inward, repeating until they meet in the middle.
Understanding the Concepts
What is the problem?
Reverse a string without using StringBuilder.reverse() or any built-in reversing helper. This tests raw array manipulation and understanding of Java's immutable String class.
Why do you need a char array?
Java strings are immutable: you cannot change their characters in place. The classic in-place reversal must happen on a mutable buffer. The natural choice is char[] c = str.toCharArray(). After reversing the array, you build a new String with new String(c).
How does the two-pointer swap work?
A left pointer at index 0 and a right pointer at the last index. At each step, swap the characters at left and right using a temporary variable, then advance left forward and right backward. Continue while left < right.
Input: "NBOI-REF-1234"
Char[]: [N, B, O, I, -, R, E, F, -, 1, 2, 3, 4]
L R
Swap N↔4, B↔3, O↔2, I↔1, -↔-, R↔F, E stays (middle)
Result: [4, 3, 2, 1, -, F, E, R, -, I, O, B, N]
Output: "4321-FER-IOBN"
How do you implement it? (with code)
package com.bank.util;
public class StringReverser {
public static String reverse(String input) {
if (input == null || input.length() <= 1) {
return input;
}
char[] chars = input.toCharArray();
int left = 0, right = chars.length - 1;
while (left < right) {
char temp = chars[left];
chars[left] = chars[right];
chars[right] = temp;
left++;
right--;
}
return new String(chars);
}
public static void main(String[] args) {
String refCode = "NBOI-TXN-5678";
System.out.println("Original: " + refCode);
System.out.println("Reversed: " + reverse(refCode));
}
}
Original: NBOI-TXN-5678
Reversed: 8765-NXT-IOBN
Why does left < right handle both odd and even lengths?
For odd length, the middle character sits exactly where left equals right. Its mirror is itself, so it does not need to move, and the loop correctly stops. For even length, the pointers cross between the two central characters after the last swap. One condition covers both cases.
Odd (5): [A, B, C, D, E]
L R → swap A↔E
L R → swap B↔D
LR → L==R, stop. C stays.
Even (4): [A, B, C, D]
L R → swap A↔D
L R → swap B↔C
R L → L>R, stop.
What about space complexity?
People sometimes claim this is O(1) extra space, but strictly speaking, because String is immutable, you must allocate the char array and then a new String, which is O(n). The algorithm on a mutable char array would be O(1) extra space. Being precise about this distinction shows you understand immutability.
| Context | Extra space |
|---|---|
| On a mutable char[] | O(1) (just the temp variable) |
| On a Java String | O(n) (char array + new String) |
What about Unicode and surrogate pairs?
Reversing by char can split a surrogate pair, which is a character represented by two char values (like emojis or rare scripts). This produces invalid text. For general Unicode, reverse by code point or detect and keep surrogate pairs together.
// Safe Unicode reversal
public static String reverseUnicode(String input) {
int[] codePoints = input.codePoints().toArray();
int left = 0, right = codePoints.length - 1;
while (left < right) {
int temp = codePoints[left];
codePoints[left] = codePoints[right];
codePoints[right] = temp;
left++;
right--;
}
return new String(codePoints, 0, codePoints.length);
}
For plain ASCII reference codes at the National Bank of India, the char-level swap is sufficient.
What are common mistakes?
// Wrong: modifying the String directly
String s = "hello";
s.charAt(0) = 'H'; // Compile error: strings are immutable
// Wrong: using left <= right (causes double-swap at middle for odd length)
while (left <= right) { // harmless but wastes a swap when left==right
swap(chars, left, right);
left++; right--;
}
// The swap at left==right is a no-op, so it is harmless but unnecessary.
// Correct:
while (left < right) { ... }
What are the edge cases?
- Empty string – return empty.
- Single character – return as-is.
- Palindrome – returns the same string.
- Null input – return null or throw.
- Spaces and special characters – reversed along with everything else.
Where is this reversal technique used as a building block?
- The two-pointer reversal is a fundamental primitive used in:
- Array rotation – triple reversal.
- Reverse words in a string – reverse whole, then reverse each word.
- Palindrome checks – compare characters from both ends.
What are common interview follow-up questions?
- Can you reverse without extra space? – Not for Java String (immutability), but yes for char[] or in languages with mutable strings.
- Reverse only vowels – move only when both pointers are on vowels.
- Reverse words in a string – reverse whole, then reverse each word.
Visual Overview
┌──────────────────────────────────────────────────────┐ │ Two-Pointer String Reversal │ ├──────────────────────────────────────────────────────┤ │ │ │ Input: "HELLO" │ │ Char[]: [H, E, L, L, O] │ │ L R │ │ │ │ Step 1: swap H ↔ O → [O, E, L, L, H] │ │ L R │ │ Step 2: swap E ↔ L → [O, L, L, E, H] │ │ LR │ │ Step 3: L == R → stop (middle L untouched) │ │ │ │ Result: "OLLEH" │ └──────────────────────────────────────────────────────┘
Key Takeaway
Reversing a string without StringBuilder is a two-pointer swap on a char array. Because Java strings are immutable, convert to a char array first, put a left pointer at the start and a right pointer at the end, swap and step inward until they cross, then build a new String from the reversed array.
The loop condition left < right cleanly handles both odd and even lengths. For odd length the middle character is left untouched because its mirror is itself. For even length the pointers cross after the final swap.
Be precise about space: the algorithm on a mutable array is O(1) extra, but on a Java String the char array and new String make it O(n), dictated by immutability. For Unicode text, reverse by code point to avoid splitting surrogate pairs.
In a banking project at the National Bank of India, this is a small receipt utility that prints a reversed transaction reference code as a visual checksum. The two-pointer reversal is also the building block for array rotation and reversing words in a string.
Remember one sentence: Convert the immutable String to a char array, swap from both ends inward with two pointers, and build a new String from the reversed array.
---