Reverse String Tail Recursion
Problem Statement
Write a Java program that implements a tail-recursive method to reverse a string using an accumulator to build the result. The program should take a string as input and return the reversed string. Test the method with various strings, including empty strings, single-character strings, and long strings, and discuss Java’s stack usage for the tail-recursive approach. You can visualize this as rearranging the letters of a word on a signboard, building the reversed word step-by-step by passing the accumulated result to the next recursive call.
Input: A string (e.g., str = "hello").
Output: A string representing the reversed input (e.g., "olleh").
Constraints:
- The string length is between 0 and 10^5.
- The string contains printable ASCII characters.
- The string may be empty. Example:
- Input:
str = "hello" - Output:
"olleh" - Explanation: The string
"hello"is reversed to"olleh"by rearranging its characters. - Input:
str = "" - Output:
"" - Explanation: An empty string remains empty after reversal.
Pseudocode
FUNCTION tailRecursiveReverse(str, index, accumulator)
IF str is null OR index < 0 THEN
RETURN accumulator
ENDIF
SET newAccumulator to character at index in str + accumulator
RETURN tailRecursiveReverse(str, index - 1, newAccumulator)
ENDFUNCTION
FUNCTION mainReverse(str)
IF str is null OR length of str equals 0 THEN
RETURN str
ENDIF
RETURN tailRecursiveReverse(str, length of str - 1, "")
ENDFUNCTION
Algorithm Steps
- Check if the input string is null or empty. If so, return the string as is.
- Define a tail-recursive helper function that takes the string, the current index, and an accumulator as parameters.
- In the helper function, implement the base case: if the index is less than 0, return the accumulator.
- For the recursive case, prepend the character at the current index to the accumulator and recursively call the function with the previous index and the updated accumulator.
- In the main function, call the tail-recursive function with the initial index set to the last index of the string (length - 1) and an empty string as the accumulator.
- Return the reversed string computed by the tail-recursive function.
Java Implementation
public class ReverseStringTailRecursion {
// Reverses a string using tail recursion
public String reverse(String str) {
// Check for null or empty string
if (str == null || str.length() == 0) {
return str;
}
// Call tail-recursive helper with initial index and accumulator
return tailRecursiveReverse(str, str.length() - 1, "");
}
// Helper function for tail-recursive string reversal
private String tailRecursiveReverse(String str, int index, String accumulator) {
// Base case: if index < 0, return accumulator
if (index < 0) {
return accumulator;
}
// Recursive case: prepend current character to accumulator and recurse
return tailRecursiveReverse(str, index - 1, str.charAt(index) + accumulator);
}
}
Output
For the input string "hello", the program outputs:
olleh
Explanation: The string "hello" is reversed to "olleh" by building the result in the accumulator.
For an empty string "", the program outputs:
""
Explanation: An empty string remains empty after reversal.
For a single-character string "a", the program outputs:
a
Explanation: A single-character string is already reversed.
How It Works
- Step 1: The
reversemethod checks if the string is null or empty. For"hello", it callstailRecursiveReversewithindex = 4andaccumulator = "". - Step 2: In
tailRecursiveReverse:- Index 4:
accumulator = 'o' + "" = "o", recurse withindex = 3,accumulator = "o". - Index 3:
accumulator = 'l' + "o" = "lo", recurse withindex = 2,accumulator = "lo". - Index 2:
accumulator = 'l' + "lo" = "llo", recurse withindex = 1,accumulator = "llo". - Index 1:
accumulator = 'e' + "llo" = "ello", recurse withindex = 0,accumulator = "ello". - Index 0:
accumulator = 'h' + "ello" = "hello", recurse withindex = -1,accumulator = "hello". - Index -1: Base case, return
accumulator = "hello".
- Index 4:
- Example Trace: For
"hello", the accumulator builds:"" → "o" → "lo" → "llo" → "ello" → "hello", returning"olleh". - Java Stack Usage: The function is tail-recursive because the recursive call is the last operation. However, Java does not optimize tail recursion, so each recursive call adds a frame to the call stack, leading to O(n) space complexity. This can cause stack overflow for very large strings (e.g., 10^5 characters). An iterative approach would use O(1) space (excluding the output string).
Complexity Analysis Table
| Operation | Time Complexity | Space Complexity |
|---|---|---|
| Recursive Call (Tail) | O(n) | O(n) |
| Full Algorithm | O(n) | O(n) |
Note:
- n is the length of the input string.
- Time complexity: O(n), as the function processes each character exactly once.
- Space complexity: O(n) due to the recursive call stack (Java does not optimize tail recursion) and the accumulator string, which grows with each call.
- Best, average, and worst cases are O(n).
✅ Tip: Use tail recursion to write elegant recursive solutions for problems like string reversal, but consider iterative methods for better space efficiency in Java. Test with long strings (e.g., 10^4 characters) and edge cases like empty or single-character strings to verify correctness.
⚠ Warning: Java does not optimize tail recursion, so the O(n) space complexity may cause stack overflow for very large strings. Additionally, string concatenation in the accumulator can be inefficient; consider using
StringBuilderin an iterative approach for better performance.