String manipulation is a fundamental aspect of programming that often appears in coding interviews, competitive programming, and real-world applications. One interesting problem that involves string manipulation is the “Reverse Vowels of a String” problem. This problem requires a deep understanding of string processing, efficient use of pointers, and the ability to handle various edge cases. In this blog, we’ll explore the problem in detail, discuss different approaches to solving it, provide examples, and explain the underlying algorithms that make the solution efficient and robust.

Problem Statement

The “Reverse Vowels of a String” problem can be stated as follows:

Given a string s, reverse only the vowels of the string and return the resulting string.

Example:

Input: s = "hello"
Output: "holle"
Input: s = "leetcode"
Output: "leotcede"

Constraints:

  • The string will consist of printable ASCII characters.
  • The string’s length will be within the range [1, 3 * 10^5].
  • Vowels are defined as ‘a’, ‘e’, ‘i’, ‘o’, ‘u’ (both uppercase and lowercase).

Understanding the Problem

The problem is simple in concept but requires careful consideration of various factors. The goal is to reverse only the vowels in the string while keeping the positions of all other characters unchanged. For example, in the string “hello”, the vowels ‘e’ and ‘o’ are swapped to produce “holle”. The key challenge here is efficiently identifying vowels and reversing them without affecting the overall structure of the string.

Approach to Solve the Problem

To solve the “Reverse Vowels of a String” problem, several approaches can be considered, each with its own trade-offs in terms of time complexity and implementation complexity. We will explore two main approaches: a straightforward method using an auxiliary array and a more optimized two-pointer technique.

1. Simple Approach Using an Auxiliary Array

This approach involves using an auxiliary array to store the vowels in the string and then reversing them.

Steps:
  1. Identify Vowels: Traverse the string and store all the vowels in an auxiliary array.
  2. Reverse the Vowels: Reverse the order of the vowels in the auxiliary array.
  3. Replace Vowels in the String: Traverse the string again, and whenever a vowel is encountered, replace it with the corresponding reversed vowel from the auxiliary array.
  4. Return the Result: Construct the final string with the reversed vowels in their new positions.
Time Complexity:
  • The time complexity of this approach is O(n), where n is the length of the string. This is because we traverse the string twice (once to identify vowels and once to replace them). The space complexity is also O(n) due to the use of the auxiliary array to store the vowels.
Code Implementation:
def reverseVowels(s: str) -> str:
    vowels = []
    for char in s:
        if char in "aeiouAEIOU":
            vowels.append(char)

    result = []
    vowel_idx = len(vowels) - 1
    for char in s:
        if char in "aeiouAEIOU":
            result.append(vowels[vowel_idx])
            vowel_idx -= 1
        else:
            result.append(char)

    return ''.join(result)

# Example usage:
s = "hello"
print(reverseVowels(s))  # Output: "holle"

While this approach is straightforward and easy to understand, it is not the most space-efficient due to the auxiliary array.

2. Optimized Approach Using the Two-Pointer Technique

A more efficient approach to solving the problem is using the two-pointer technique. This method eliminates the need for an auxiliary array, thereby reducing the space complexity.

Steps:
  1. Initialize Two Pointers: Start with two pointers, one at the beginning (left) and one at the end (right) of the string.
  2. Find Vowels Using the Pointers:
  • Move the left pointer from the start towards the end of the string until it finds a vowel.
  • Move the right pointer from the end towards the start of the string until it finds a vowel.
  1. Swap the Vowels: Swap the vowels at the left and right pointers.
  2. Move the Pointers:
  • Move the left pointer forward and the right pointer backward.
  • Continue this process until the two pointers meet or cross each other.
  1. Return the Result: The string with the vowels reversed in place is the final result.
Time Complexity:
  • The time complexity of this approach is O(n) because each character in the string is processed at most once. The space complexity is O(1) since no additional space is used beyond a few variables.
Code Implementation:

Here is the implementation of the two-pointer approach in Python:

def reverseVowels(s: str) -> str:
    vowels = "aeiouAEIOU"
    s = list(s)
    left, right = 0, len(s) - 1

    while left < right:
        while left < right and s[left] not in vowels:
            left += 1
        while left < right and s[right] not in vowels:
            right -= 1
        s[left], s[right] = s[right], s[left]
        left += 1
        right -= 1

    return ''.join(s)

# Example usage:
s = "leetcode"
print(reverseVowels(s))  # Output: "leotcede"

This approach is both time-efficient and space-efficient, making it suitable for large strings.

Detailed Example

Let’s walk through an example step by step using the two-pointer approach.

Example:

Input: s = "leetcode"
Output: "leotcede"

Step-by-Step Process:

  1. Initialization:
  • Start with left = 0 (pointing to ‘l’) and right = 7 (pointing to ‘e’).
  • The string is “leetcode”.
  1. First Iteration:
  • left moves to index 1 (‘e’), which is a vowel.
  • right moves to index 7 (‘e’), which is also a vowel.
  • Swap the vowels: no change since both are ‘e’.
  • Move left to 2 and right to 6.
  1. Second Iteration:
  • left moves to index 2 (‘o’), which is a vowel.
  • right moves to index 6 (‘d’), which is not a vowel, so right moves to index 5 (‘c’), then to index 4 (‘o’), which is a vowel.
  • Swap the vowels: ‘o’ and ‘e’.
  • The string becomes “leotcede”.
  • Move left to 3 and right to 3.
  1. Termination:
  • The pointers have met, so the process stops.
  • The final string is “leotcede”.

Edge Cases

When solving the Reverse Vowels of a String problem, consider the following edge cases:

  1. String with No Vowels: If the string contains no vowels, the output should be the same as the input. For example, “bcdfg” should return “bcdfg”.
  2. String with Only One Vowel: If the string has only one vowel, no swaps should occur. For example, “abcd” should return “abcd”.
  3. Empty String: An empty string should return an empty string.
  4. All Vowels: If the string consists entirely of vowels, the entire string should be reversed. For example, “aeiou” should return “uoiea”.

Complexity Analysis

  • Time Complexity: Both the simple and optimized approaches have a time complexity of O(n), where n is the length of the string. This is because each character in the string is processed at most once.
  • Space Complexity: The simple approach using an auxiliary array has a space complexity of O(n), while the optimized two-pointer approach has a space complexity of O(1).

Practical Applications

The “Reverse Vowels of a String” problem, while seemingly simple, has practical applications in text processing and natural language processing (NLP). For instance, it could be used in data obfuscation, where vowels in sensitive text are reversed to create a simple cipher. It can also serve as a basic exercise in learning about in-place modifications, pointers, and efficient string manipulation techniques.

The “Reverse Vowels of a String” problem is a great way to practice string manipulation and the use of pointers in algorithms. By mastering both the simple and optimized approaches, you not only learn how to reverse elements within a string efficiently but also gain insight into solving similar problems that involve selective manipulation of string characters.

Further Exploration

For those looking to deepen their understanding, consider extending the problem to handle more complex scenarios, such as reversing consonants, or manipulating other specific character sets within a string. Additionally, you could implement the solution in different programming languages or optimize it for specific use cases, such as large-scale text processing.


By mastering the “Reverse Vowels of a String” problem, you’ll gain valuable skills in string manipulation, algorithm design, and pointer-based techniques, making you a more effective problem solver in both academic and professional settings. Happy coding!

LEAVE A REPLY

Please enter your comment!
Please enter your name here