TechByteByByte

Reverse a String Without Using Built-in Methods - Java

An easy QA/automation coding interview question: reverse a String Without Using Built-in Methods, with a full Java walkthrough, dry run, and common interviewer follow-ups.

#Strings#Loops#StringBuilder#Easy#Java

Category: Easy | Concepts used: Two-pointer array swaps, String immutability, Heap heap space minimization


Problem Statement

Given a string, reverse it without using StringBuilder.reverse() or any other ready-made reverse method.

Input : "hello"      Output: "olleh"
Input : "a"           Output: "a"

Examples (with edge scenarios)

#InputOutputWhy
1"hello""olleh"Typical word
2""""Empty string check
3"a""a"Single character is symmetric
4"racecar""racecar"Palindrome
5"ab cd""dc ba"Spaces treated as characters

โš ๏ธ Common Beginner Mistake

MistakeImpactFix
Bypassing the check with new StringBuilder(str).reverse()Skips evaluating your logical loop capabilitiesWrite the manual loop logic first, unless built-in methods are explicitly permitted
Off-by-one errors during manual decrement loopsMissing character boundaries, causing StringIndexOutOfBoundsExceptionSet the loop boundary index to start at str.length() - 1 down to >= 0 inclusive

Before You Code: Clarify the Contract

Before choosing an algorithm, confirm how null and empty strings should behave, whether comparison is case-sensitive, and whether spaces or punctuation count. Java char values are UTF-16 code units, not always complete human-visible Unicode characters, so international text may require code points or grapheme-aware libraries.

Analogy: Swapping Passenger Seats on a Train

Imagine a row of passengers sitting in numbered seats on a train:

  • Solution 1 (Creating a new line): You ask everyone to stand up and form a new line starting from the back of the train, copying each passenger to their new seat one by one. If you do this with a stack of cards, you keep making copies of the entire stack every time you add a card, which is extremely slow.
  • Solution 2 (Two-Pointer Swap): You have two supervisors: one starts at the front of the train (Left) and one at the back (Right).
    • They point to two passengers and ask them to swap seats.
    • The Left supervisor takes a step right (left++), and the Right supervisor takes a step left (right--).
    • They swap the next pair.
    • They repeat this until they meet in the middle. No one else has to move, and no extra train is needed!

Solution 1 โ€” Loop from the End, Build a New String (Basic)

This is the standard manual approach, iterating backward.

Intuition

By reading the string from the last index (length() - 1) back to index 0, we can append each character to a new result accumulator.

public class ReverseStringLoop {
    public static String reverseString(String str) {
        if (str == null || str.isEmpty()) {
            return str;
        }

String result = "";
        for (int i = str.length() - 1; i >= 0; i--) {
            result += str.charAt(i); // Appending characters in reverse
        }
        return result;
    }

public static void main(String[] args) {
        System.out.println(reverseString("hello"));  // "olleh"
        System.out.println(reverseString(""));        // ""
        System.out.println(reverseString("a"));        // "a"
    }
}

Output:

olleh

a

Dry Run (str = โ€œcatโ€)

i = 2: ch = 't' -> result = "t"
i = 1: ch = 'a' -> result = "ta"
i = 0: ch = 'c' -> result = "tac"
Final result = "tac"

Solution 2 โ€” Using a char[] Array with Two Pointers (Optimal)

This is the most efficient manual approach, minimizing intermediate string copies.

Intuition

Java strings are immutable, so repeatedly adding to them using result += ch allocates a new string on every character. Instead, we can copy the string into a mutable character array once, swap elements in place from both ends, and convert it back to a string.

public class ReverseStringTwoPointer {
    public static String reverseString(String str) {
        if (str == null || str.isEmpty()) {
            return str;
        }

char[] chars = str.toCharArray(); // Mutable character representation
        int left = 0;
        int right = chars.length - 1;

while (left < right) {
            // Swap character elements
            char temp = chars[left];
            chars[left] = chars[right];
            chars[right] = temp;

// Move pointers inward
            left++;
            right--;
        }
        return new String(chars);
    }

public static void main(String[] args) {
        System.out.println(reverseString("hello")); // "olleh"
        System.out.println(reverseString("ab cd"));   // "dc ba"
    }
}

Output:

olleh
dc ba

๐Ÿ“Š Visual Flowchart

graph TD
    Start["Given String S"] --> Empty{"S is null or empty?"}
    Empty -->|Yes| RetSelf["Return S"]
    Empty -->|No| ToArray["chars = S.toCharArray()"]
    ToArray --> InitPtr["left = 0, right = chars.length - 1"]
    InitPtr --> Compare{"left < right?"}
    Compare -->|Yes| Swap["swap chars[left] and chars[right]"]
    Swap --> Adjust["left++, right--"]
    Adjust --> Compare
    Compare -->|No| Convert["New String(chars)"]
    Convert --> End["Return reversed string"]

Interviewer Insights

This is a core QA interview question designed to evaluate memory footprint awareness.

Follow-up questions you might get:

  • โ€œWhat is the time complexity of Solution 1?โ€ โ†’ Solution 1 runs in (O(N^2)) time. Because strings are immutable, concatenating a character creates a new string copy. Copying a string of size (k) takes (O(k)) time. Summing this over (N) characters yields: โˆ‘k=1Nk=N(N+1)2=O(N2)\sum_{k=1}^{N} k = \frac{N(N+1)}{2} = O(N^2) Solution 2 operates in linear (O(N)) time because array swaps are (O(1)) memory modifications.
  • โ€œHow would you check if the string contains multi-byte Unicode characters (surrogate pairs)?โ€ โ†’ Standard char indexing can break surrogate pairs (e.g. emojis). For production support, you would need to iterate using Unicode code points (str.codePoints()).

Quick Recap

ApproachHeap AllocationTime ComplexityAuxiliary Space ComplexityInterview Signal
Backward Loop (+=)High (creates (N) strings)(O(N^2))(O(N))Demonstrates basic logic, but shows poor memory awareness
Two-Pointer SwapLow (only 1 char array)(O(N))(O(N))Optimal manual swap, showing two-pointer pattern mastery
StringBuilder.reverse()Low(O(N))(O(N))Concise, preferred only if built-ins are permitted
Author
TechByteByByte Editorial Team
Reviewed by
TechByteByByte Admin
Published
Last reviewed