TopicsStringString Reversal
📖

String Reversal

String
~20 min read
5 practice problems

Overview

String reversal is a fundamental string manipulation operation that involves reversing the order of characters in a string. While seemingly simple, string reversal problems test your understanding of two pointers, in-place algorithms, and efficient string manipulation techniques.

Common reversal problems include:

  • Reverse entire string
  • Reverse words in a string
  • Reverse substring
  • Reverse string in-place
  • Reverse only vowels/consonants
  • Reverse string with constraints
  • Reverse k characters at a time

Pattern 1: Reverse Entire String

Reverse all characters in a string.

Approach 1: Two Pointers

function reverseString(s: string[]): void {
  let left = 0;
  let right = s.length - 1;
  
  while (left < right) {
    // Swap characters
    [s[left], s[right]] = [s[right], s[left]];
    left++;
    right--;
  }
}

Time: O(n), Space: O(1)

Approach 2: Built-in Methods

function reverseStringBuiltIn(s: string): string {
  return s.split('').reverse().join('');
}

Time: O(n), Space: O(n)

Approach 3: Recursive

function reverseStringRecursive(s: string[]): void {
  function reverse(left: number, right: number) {
    if (left >= right) return;
    [s[left], s[right]] = [s[right], s[left]];
    reverse(left + 1, right - 1);
  }
  reverse(0, s.length - 1);
}

Time: O(n), Space: O(n) for recursion stack


Pattern 2: Reverse Words in a String

Reverse the order of words while preserving spaces.

Example: "the sky is blue" → "blue is sky the"

Approach 1: Split and Reverse

function reverseWords(s: string): string {
  return s.trim().split(/\s+/).reverse().join(' ');
}

Time: O(n), Space: O(n)

Approach 2: Manual Reversal

function reverseWordsManual(s: string): string {
  const words: string[] = [];
  let word = '';
  
  for (let i = 0; i < s.length; i++) {
    if (s[i] === ' ') {
      if (word) {
        words.push(word);
        word = '';
      }
    } else {
      word += s[i];
    }
  }
  
  if (word) words.push(word);
  
  return words.reverse().join(' ');
}

In-place reversal (O(1) space):

function reverseWordsInPlace(s: string[]): void {
  // Reverse entire string
  reverseRange(s, 0, s.length - 1);
  
  // Reverse each word
  let start = 0;
  for (let i = 0; i <= s.length; i++) {
    if (i === s.length || s[i] === ' ') {
      reverseRange(s, start, i - 1);
      start = i + 1;
    }
  }
}

function reverseRange(arr: string[], left: number, right: number): void {
  while (left < right) {
    [arr[left], arr[right]] = [arr[right], arr[left]];
    left++;
    right--;
  }
}

Time: O(n), Space: O(1)


Pattern 3: Reverse Substring

Reverse a specific substring within a string.

function reverseSubstring(s: string, start: number, end: number): string {
  const arr = s.split('');
  
  while (start < end) {
    [arr[start], arr[end]] = [arr[end], arr[start]];
    start++;
    end--;
  }
  
  return arr.join('');
}

Reverse substring in-place:

function reverseSubstringInPlace(s: string[], start: number, end: number): void {
  while (start < end) {
    [s[start], s[end]] = [s[end], s[start]];
    start++;
    end--;
  }
}

Time: O(k) where k is substring length, Space: O(1)


Pattern 4: Reverse Only Vowels

Reverse only vowel characters, keeping consonants in place.

function reverseVowels(s: string): string {
  const vowels = new Set(['a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U']);
  const arr = s.split('');
  let left = 0;
  let right = arr.length - 1;
  
  while (left < right) {
    // Find next vowel from left
    while (left < right && !vowels.has(arr[left])) {
      left++;
    }
    
    // Find next vowel from right
    while (left < right && !vowels.has(arr[right])) {
      right--;
    }
    
    // Swap vowels
    if (left < right) {
      [arr[left], arr[right]] = [arr[right], arr[left]];
      left++;
      right--;
    }
  }
  
  return arr.join('');
}

Example: "hello" → "holle"

Time: O(n), Space: O(1)


Pattern 5: Reverse Only Consonants

Reverse only consonant characters, keeping vowels in place.

function reverseConsonants(s: string): string {
  const vowels = new Set(['a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U']);
  const arr = s.split('');
  let left = 0;
  let right = arr.length - 1;
  
  while (left < right) {
    // Find next consonant from left
    while (left < right && vowels.has(arr[left])) {
      left++;
    }
    
    // Find next consonant from right
    while (left < right && vowels.has(arr[right])) {
      right--;
    }
    
    // Swap consonants
    if (left < right) {
      [arr[left], arr[right]] = [arr[right], arr[left]];
      left++;
      right--;
    }
  }
  
  return arr.join('');
}

Pattern 6: Reverse K Characters at a Time

Reverse every k characters in the string.

function reverseKChars(s: string, k: number): string {
  const arr = s.split('');
  
  for (let i = 0; i < arr.length; i += k) {
    const end = Math.min(i + k - 1, arr.length - 1);
    reverseRange(arr, i, end);
  }
  
  return arr.join('');
}

function reverseRange(arr: string[], left: number, right: number): void {
  while (left < right) {
    [arr[left], arr[right]] = [arr[right], arr[left]];
    left++;
    right--;
  }
}

Example: "abcdefg" with k=2 → "badcfeg"

Time: O(n), Space: O(1)

Reverse first k, keep next k, repeat:

function reverseKAlternating(s: string, k: number): string {
  const arr = s.split('');
  let i = 0;
  
  while (i < arr.length) {
    // Reverse first k
    const end = Math.min(i + k - 1, arr.length - 1);
    reverseRange(arr, i, end);
    
    // Skip next k
    i += 2 * k;
  }
  
  return arr.join('');
}

Example: "abcdefgh" with k=2 → "bacdefgh" (reverse first 2, skip next 2)


Pattern 7: Reverse String with Constraints

Reverse string while preserving certain characters or positions.

Reverse but keep spaces:

function reverseKeepSpaces(s: string): string {
  const arr = s.split('');
  const spaceIndices = new Set<number>();
  
  // Find space positions
  for (let i = 0; i < arr.length; i++) {
    if (arr[i] === ' ') {
      spaceIndices.add(i);
    }
  }
  
  // Collect non-space characters
  const chars: string[] = [];
  for (const char of arr) {
    if (char !== ' ') {
      chars.push(char);
    }
  }
  
  // Reverse non-space characters
  chars.reverse();
  
  // Rebuild with spaces
  const result: string[] = [];
  let charIndex = 0;
  
  for (let i = 0; i < arr.length; i++) {
    if (spaceIndices.has(i)) {
      result.push(' ');
    } else {
      result.push(chars[charIndex++]);
    }
  }
  
  return result.join('');
}

Reverse but keep special characters:

function reverseKeepSpecial(s: string): string {
  const arr = s.split('');
  const special = /[^a-zA-Z0-9]/;
  const chars: string[] = [];
  const positions: number[] = [];
  
  // Collect alphanumeric characters and their positions
  for (let i = 0; i < arr.length; i++) {
    if (!special.test(arr[i])) {
      chars.push(arr[i]);
      positions.push(i);
    }
  }
  
  // Reverse alphanumeric characters
  chars.reverse();
  
  // Place reversed characters back
  for (let i = 0; i < positions.length; i++) {
    arr[positions[i]] = chars[i];
  }
  
  return arr.join('');
}

Pattern 8: Reverse Prefix/Suffix

Reverse a prefix or suffix of the string.

Reverse prefix of length k:

function reversePrefix(s: string, k: number): string {
  if (k >= s.length) return s.split('').reverse().join('');
  
  const arr = s.split('');
  reverseRange(arr, 0, k - 1);
  return arr.join('');
}

Reverse suffix of length k:

function reverseSuffix(s: string, k: number): string {
  if (k >= s.length) return s.split('').reverse().join('');
  
  const arr = s.split('');
  const start = arr.length - k;
  reverseRange(arr, start, arr.length - 1);
  return arr.join('');
}

Reverse prefix until first occurrence of character:

function reversePrefixUntil(s: string, ch: string): string {
  const index = s.indexOf(ch);
  if (index === -1) return s;
  
  const arr = s.split('');
  reverseRange(arr, 0, index);
  return arr.join('');
}

Pattern 9: Reverse String by Words (Preserve Formatting)

Reverse words while preserving multiple spaces and formatting.

function reverseWordsPreserveSpaces(s: string): string {
  const words: string[] = [];
  const spaces: string[] = [];
  let currentWord = '';
  let currentSpace = '';
  
  for (let i = 0; i < s.length; i++) {
    if (s[i] === ' ') {
      if (currentWord) {
        words.push(currentWord);
        currentWord = '';
      }
      currentSpace += ' ';
    } else {
      if (currentSpace) {
        spaces.push(currentSpace);
        currentSpace = '';
      }
      currentWord += s[i];
    }
  }
  
  if (currentWord) words.push(currentWord);
  if (currentSpace) spaces.push(currentSpace);
  
  words.reverse();
  
  const result: string[] = [];
  const maxLen = Math.max(words.length, spaces.length);
  
  for (let i = 0; i < maxLen; i++) {
    if (i < words.length) result.push(words[i]);
    if (i < spaces.length) result.push(spaces[i]);
  }
  
  return result.join('');
}

Pattern 10: Reverse String in Chunks

Reverse string by dividing into chunks and reversing each chunk.

function reverseChunks(s: string, chunkSize: number): string {
  const arr = s.split('');
  
  for (let i = 0; i < arr.length; i += chunkSize) {
    const end = Math.min(i + chunkSize - 1, arr.length - 1);
    reverseRange(arr, i, end);
  }
  
  return arr.join('');
}

Reverse chunks themselves (not characters within chunks):

function reverseChunkOrder(s: string, chunkSize: number): string {
  const chunks: string[] = [];
  
  for (let i = 0; i < s.length; i += chunkSize) {
    chunks.push(s.substring(i, Math.min(i + chunkSize, s.length)));
  }
  
  return chunks.reverse().join('');
}

Example: "abcdefgh" with chunkSize=2 → "ghefcdab" (chunks: ab, cd, ef, gh → reversed: gh, ef, cd, ab)


Pattern 11: Reverse String with Character Mapping

Reverse string while applying character transformations.

Reverse and swap case:

function reverseAndSwapCase(s: string): string {
  const arr = s.split('');
  let left = 0;
  let right = arr.length - 1;
  
  while (left < right) {
    const temp = arr[left];
    arr[left] = arr[right].toUpperCase() === arr[right] 
      ? arr[right].toLowerCase() 
      : arr[right].toUpperCase();
    arr[right] = temp.toUpperCase() === temp 
      ? temp.toLowerCase() 
      : temp.toUpperCase();
    left++;
    right--;
  }
  
  return arr.join('');
}

Reverse and apply transformation:

function reverseWithTransform(s: string, transform: (char: string) => string): string {
  const arr = s.split('');
  let left = 0;
  let right = arr.length - 1;
  
  while (left < right) {
    [arr[left], arr[right]] = [transform(arr[right]), transform(arr[left])];
    left++;
    right--;
  }
  
  if (left === right) {
    arr[left] = transform(arr[left]);
  }
  
  return arr.join('');
}

Pattern 12: Reverse String Based on Condition

Reverse parts of string based on specific conditions.

Reverse only alphabetic characters:

function reverseAlphabetic(s: string): string {
  const arr = s.split('');
  const alphabetic: string[] = [];
  const positions: number[] = [];
  
  // Collect alphabetic characters
  for (let i = 0; i < arr.length; i++) {
    if (/[a-zA-Z]/.test(arr[i])) {
      alphabetic.push(arr[i]);
      positions.push(i);
    }
  }
  
  // Reverse alphabetic characters
  alphabetic.reverse();
  
  // Place back
  for (let i = 0; i < positions.length; i++) {
    arr[positions[i]] = alphabetic[i];
  }
  
  return arr.join('');
}

Reverse characters at even/odd indices:

function reverseEvenIndices(s: string): string {
  const arr = s.split('');
  const evenChars: string[] = [];
  
  for (let i = 0; i < arr.length; i += 2) {
    evenChars.push(arr[i]);
  }
  
  evenChars.reverse();
  
  for (let i = 0, j = 0; i < arr.length; i += 2) {
    arr[i] = evenChars[j++];
  }
  
  return arr.join('');
}

When to Use String Reversal

Use reversal techniques when:

  • Problem asks about "reverse", "flip", or "invert"
  • Need to reverse words or substrings
  • In-place modification is required
  • Selective reversal (vowels, consonants, etc.)
  • Pattern-based reversal (k characters, chunks)
  • Palindrome or symmetric problems

Template (Basic Reversal)

function reverseTemplate(s: string[]): void {
  let left = 0;
  let right = s.length - 1;
  
  while (left < right) {
    [s[left], s[right]] = [s[right], s[left]];
    left++;
    right--;
  }
}

Template (Reverse Range)

function reverseRangeTemplate(arr: string[], left: number, right: number): void {
  while (left < right) {
    [arr[left], arr[right]] = [arr[right], arr[left]];
    left++;
    right--;
  }
}

Template (Selective Reversal)

function reverseSelectiveTemplate(s: string[], condition: (char: string) => boolean): void {
  let left = 0;
  let right = s.length - 1;
  
  while (left < right) {
    // Skip non-matching from left
    while (left < right && !condition(s[left])) {
      left++;
    }
    
    // Skip non-matching from right
    while (left < right && !condition(s[right])) {
      right--;
    }
    
    // Swap matching characters
    if (left < right) {
      [s[left], s[right]] = [s[right], s[left]];
      left++;
      right--;
    }
  }
}

Time and Space Complexity Summary

  • Basic reversal: O(n) time, O(1) space (in-place)
  • Reverse words: O(n) time, O(n) space (split), O(1) space (in-place)
  • Reverse substring: O(k) time where k is substring length, O(1) space
  • Selective reversal: O(n) time, O(1) space
  • Chunk reversal: O(n) time, O(1) space

Practice Tips

  1. Use two pointers — Most efficient for in-place reversal
  2. Handle edge cases — Empty strings, single character, all same characters
  3. Consider in-place — When space optimization is critical
  4. Preserve formatting — Be careful with spaces and special characters
  5. Optimize swaps — Use destructuring for cleaner code
  6. Test boundaries — Check start/end indices carefully

Common Mistakes

  1. Off-by-one errors — Be careful with array indices
  2. Not handling empty strings — Check length before processing
  3. Modifying during iteration — Be careful with in-place modifications
  4. Case sensitivity — Consider case when reversing selectively
  5. Space handling — Preserve or remove spaces as required

Related Concepts

  • Two Pointers — Core technique for reversal
  • String Manipulation — Building reversed strings
  • In-Place Algorithms — Space-efficient reversal
  • Palindrome Problems — Often use reversal techniques

String reversal is a fundamental operation that appears in many string problems. Master two-pointer reversal and in-place techniques, and you'll be well-prepared for reversal-related interview questions.