LeetCode 1119 - Remove Vowels from a String
The problem asks us to remove vowels from a given string s. Specifically, the vowels are defined as the lowercase characters 'a', 'e', 'i', 'o', and 'u'. The input string consists only of lowercase English letters, and its length ranges from 1 to 1000.
Difficulty: 🟢 Easy
Topics: String
Solution
Problem Understanding
The problem asks us to remove vowels from a given string s. Specifically, the vowels are defined as the lowercase characters 'a', 'e', 'i', 'o', and 'u'. The input string consists only of lowercase English letters, and its length ranges from 1 to 1000. The expected output is a string that contains all the original characters from s except for the vowels, preserving the original order of the consonants.
The constraints are fairly small: a maximum of 1000 characters means that even simple iterative solutions will run efficiently. Edge cases include strings that are all vowels, strings with no vowels, and strings with a single character. These edge cases could easily trip up a naive implementation if, for example, it assumes there is at least one consonant.
Approaches
A brute-force approach would iterate through each character in the string and, for every character, check if it is a vowel. If it is not a vowel, we append it to a new string. This approach works correctly, but it involves repeated membership tests that can be optimized.
The optimal approach uses a set to store the vowels. By using a set, membership checking becomes O(1) per character. We then iterate through the string once, building a new string (or list of characters) that excludes vowels. This approach is straightforward, efficient, and leverages a simple Python or Go idiom for string building.
| Approach | Time Complexity | Space Complexity | Notes |
|---|---|---|---|
| Brute Force | O(n * m) | O(n) | Check each character against a list of vowels (m = number of vowels, 5) |
| Optimal | O(n) | O(n) | Use a set for O(1) membership checks and build result incrementally |
Algorithm Walkthrough
- Create a set containing all vowels:
{'a', 'e', 'i', 'o', 'u'}. This allows O(1) membership checking for each character. - Initialize an empty list to store the resulting characters.
- Iterate over each character in the input string.
- For each character, check if it is not in the vowels set.
- If it is not a vowel, append it to the result list.
- After processing all characters, join the list into a single string.
- Return the resulting string.
Why it works: The algorithm guarantees that every character from the original string is examined exactly once, and only non-vowel characters are preserved. Using a set ensures efficient vowel checking, and constructing a new string preserves the order of the consonants.
Python Solution
class Solution:
def removeVowels(self, s: str) -> str:
vowels = {'a', 'e', 'i', 'o', 'u'}
result = []
for char in s:
if char not in vowels:
result.append(char)
return ''.join(result)
The Python implementation follows the algorithm directly. We first define a set of vowels, then initialize an empty list result to accumulate consonants. For each character in the string, we check if it is not a vowel, appending it to result if it passes the test. Finally, ''.join(result) concatenates the list into a single string to return.
Go Solution
func removeVowels(s string) string {
vowels := map[rune]bool{
'a': true,
'e': true,
'i': true,
'o': true,
'u': true,
}
result := []rune{}
for _, char := range s {
if !vowels[char] {
result = append(result, char)
}
}
return string(result)
}
In Go, we use a map[rune]bool to store the vowels for O(1) membership checking. The string is iterated using a for _, char := range s loop to handle each character as a rune. Non-vowel characters are appended to a slice of runes, which is then converted back to a string using string(result).
Worked Examples
Example 1: "leetcodeisacommunityforcoders"
| Iteration | char | in vowels? | result list |
|---|---|---|---|
| 1 | 'l' | no | ['l'] |
| 2 | 'e' | yes | ['l'] |
| 3 | 'e' | yes | ['l'] |
| 4 | 't' | no | ['l', 't'] |
| 5 | 'c' | no | ['l', 't', 'c'] |
| 6 | 'o' | yes | ['l', 't', 'c'] |
| ... | ... | ... | ... |
| final | - | - | ['l', 't', 'c', 'd', 's', 'c', 'm', 'm', 'n', 't', 'y', 'f', 'r', 'c', 'd', 'r', 's'] |
Output: "ltcdscmmntyfrcdrs"
Example 2: "aeiou"
All characters are vowels, so the result list remains empty. Output: "".
Complexity Analysis
| Measure | Complexity | Explanation |
|---|---|---|
| Time | O(n) | We iterate through each character once and perform O(1) membership checks in a set |
| Space | O(n) | We store up to n characters in the result list |
Because n is at most 1000, both time and space usage are trivial for modern systems.
Test Cases
# Provided examples
assert Solution().removeVowels("leetcodeisacommunityforcoders") == "ltcdscmmntyfrcdrs" # mixed string
assert Solution().removeVowels("aeiou") == "" # all vowels
# Boundary cases
assert Solution().removeVowels("b") == "b" # single consonant
assert Solution().removeVowels("a") == "" # single vowel
# No vowels
assert Solution().removeVowels("bcdfghjklmnpqrstvwxyz") == "bcdfghjklmnpqrstvwxyz" # all consonants
# Mixed vowels and consonants
assert Solution().removeVowels("programmingisfun") == "prgrmmngsfn" # mixed string
| Test | Why |
|---|---|
"leetcodeisacommunityforcoders" |
general mixed input |
"aeiou" |
all vowels removed |
"b" |
single consonant edge case |
"a" |
single vowel edge case |
"bcdfghjklmnpqrstvwxyz" |
no vowels, ensure consonants are preserved |
"programmingisfun" |
standard mixed string |
Edge Cases
One edge case is a string consisting entirely of vowels, such as "aeiou". This tests whether the implementation correctly returns an empty string rather than accidentally inserting placeholder characters. Our solution handles this naturally by only appending non-vowels to the result list.
A second edge case is a string consisting entirely of consonants. This tests that the algorithm does not remove valid characters. Using a set membership check ensures that all consonants are preserved because they are never in the vowel set.
A third edge case is a single-character string, either a vowel or consonant. This is important to ensure that the algorithm handles minimal input sizes without errors, and our implementation correctly returns either the same character or an empty string depending on whether the character is a vowel.