Facebook Pixel

3136. Valid Word

EasyString
Leetcode Link

Problem Description

You need to determine if a given word is valid based on specific criteria.

A word is considered valid if it meets ALL of the following conditions:

  1. Length requirement: The word must contain at least 3 characters
  2. Character composition: The word can only contain:
    • Digits (0-9)
    • English letters (both uppercase and lowercase)
    • No special characters or symbols are allowed
  3. Vowel requirement: The word must contain at least one vowel
    • Vowels are: 'a', 'e', 'i', 'o', 'u' and their uppercase versions 'A', 'E', 'I', 'O', 'U'
  4. Consonant requirement: The word must contain at least one consonant
    • A consonant is any English letter that is not a vowel

Given a string word, you need to return true if the word satisfies all four conditions above, otherwise return false.

Example scenarios:

  • A word like "a1b" would be valid (length ≥ 3, contains only valid characters, has vowel 'a', has consonant 'b')
  • A word like "123" would be invalid (no vowels or consonants, only digits)
  • A word like "ab" would be invalid (length < 3)
  • A word like "a@b" would be invalid (contains special character '@')
  • A word like "aaa" would be invalid (no consonants)
Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

The problem asks us to validate a word based on four distinct criteria. The key insight is that we need to check each condition systematically, and if any condition fails, we can immediately return false.

Let's think about how to approach each requirement:

  1. Length check: This is straightforward - we can check len(word) < 3 at the very beginning. If the word is too short, there's no need to check anything else.

  2. Character validation: As we traverse through each character in the word, we need to ensure it's either a digit or a letter. The built-in method isalnum() perfectly handles this - it returns true only for alphanumeric characters.

  3. Vowel and Consonant tracking: Here's where we need to be clever. Instead of making two separate passes through the string, we can track both requirements in a single pass. We'll use two boolean flags:

    • has_vowel: Initially false, set to true when we encounter any vowel
    • has_consonant: Initially false, set to true when we encounter any consonant

The trick is to pre-define a set of vowels "aeiouAEIOU". When we encounter a letter (checked using isalpha()), we can quickly determine if it's a vowel by checking membership in this set. If it's a letter but not in the vowel set, it must be a consonant.

By the end of our traversal, both flags must be true for the word to be valid. This approach is efficient because:

  • We only make one pass through the string
  • We exit early if we find an invalid character
  • Set membership checking is O(1) on average
  • We don't need to store or count individual vowels/consonants, just track their presence

Solution Approach

Let's implement the solution step by step based on our validation criteria:

Step 1: Check minimum length

if len(word) < 3:
    return False

If the word has fewer than 3 characters, we immediately return false since it fails the first requirement.

Step 2: Initialize tracking variables

has_vowel = has_consonant = False
vs = set("aeiouAEIOU")
  • We create two boolean flags to track whether we've found at least one vowel and one consonant
  • We define a set vs containing all vowels (both lowercase and uppercase) for O(1) lookup time

Step 3: Iterate through each character

for c in word:

We examine each character in the word one by one.

Step 4: Validate character type

if not c.isalnum():
    return False

For each character, we first check if it's alphanumeric (either a letter or digit). If we encounter any special character or symbol, the word is invalid, so we return false immediately.

Step 5: Check for vowels and consonants

if c.isalpha():
    if c in vs:
        has_vowel = True
    else:
        has_consonant = True

If the character is a letter (not a digit):

  • We check if it's in our vowel set vs
  • If yes, we set has_vowel = True
  • If no, it must be a consonant, so we set has_consonant = True

Note that digits don't affect our vowel/consonant requirements - they're valid characters but neither vowels nor consonants.

Step 6: Final validation

return has_vowel and has_consonant

After processing all characters, we return true only if we've found both at least one vowel AND at least one consonant. If either flag remains false, the word is invalid.

This approach efficiently validates the word in a single pass with O(n) time complexity, where n is the length of the word.

Ready to land your dream job?

Unlock your dream job with a 3-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's walk through the solution with the word "Ex4mple":

Step 1: Check minimum length

  • len("Ex4mple") = 7, which is ≥ 3 ✓
  • Continue to next step

Step 2: Initialize tracking variables

  • has_vowel = False
  • has_consonant = False
  • vs = {"a", "e", "i", "o", "u", "A", "E", "I", "O", "U"}

Step 3-5: Process each character

Characterisalnum()?isalpha()?In vowel set?Actionhas_vowelhas_consonant
'E'Yes ✓YesYes ('E' in vs)Set has_vowel = TrueTrueFalse
'x'Yes ✓YesNo ('x' not in vs)Set has_consonant = TrueTrueTrue
'4'Yes ✓NoN/ASkip (digit)TrueTrue
'm'Yes ✓YesNo ('m' not in vs)Already have consonantTrueTrue
'p'Yes ✓YesNo ('p' not in vs)Already have consonantTrueTrue
'l'Yes ✓YesNo ('l' not in vs)Already have consonantTrueTrue
'e'Yes ✓YesYes ('e' in vs)Already have vowelTrueTrue

Step 6: Final validation

  • has_vowel = True (found 'E' and 'e')
  • has_consonant = True (found 'x', 'm', 'p', 'l')
  • Return has_vowel AND has_consonant = True AND True = True

The word "Ex4mple" is valid


Counter-example with "123" (invalid - no vowels or consonants):

Step 1: len("123") = 3
Step 2: Initialize has_vowel = False, has_consonant = False
Step 3-5: Process characters:

  • '1': isalnum() ✓, but isalpha() ✗ → skip (digit)
  • '2': isalnum() ✓, but isalpha() ✗ → skip (digit)
  • '3': isalnum() ✓, but isalpha() ✗ → skip (digit)

Step 6: Return False AND False = False

The word "123" is invalid because it contains no vowels or consonants.

Solution Implementation

1class Solution:
2    def isValid(self, word: str) -> bool:
3        """
4        Validates if a word meets specific criteria:
5        - Minimum length of 3 characters
6        - Contains only alphanumeric characters
7        - Has at least one vowel
8        - Has at least one consonant
9      
10        Args:
11            word: Input string to validate
12          
13        Returns:
14            bool: True if word is valid, False otherwise
15        """
16        # Check minimum length requirement
17        if len(word) < 3:
18            return False
19      
20        # Initialize flags to track presence of vowels and consonants
21        has_vowel = False
22        has_consonant = False
23      
24        # Define set of vowels (both lowercase and uppercase)
25        vowels = set("aeiouAEIOU")
26      
27        # Iterate through each character in the word
28        for char in word:
29            # Check if character is alphanumeric (letter or digit)
30            if not char.isalnum():
31                return False
32          
33            # If character is a letter, determine if it's a vowel or consonant
34            if char.isalpha():
35                if char in vowels:
36                    has_vowel = True
37                else:
38                    has_consonant = True
39      
40        # Word is valid only if it contains both vowel(s) and consonant(s)
41        return has_vowel and has_consonant
42
1class Solution {
2    public boolean isValid(String word) {
3        // Check if word has minimum length of 3
4        if (word.length() < 3) {
5            return false;
6        }
7      
8        // Track whether word contains required characters
9        boolean hasVowel = false;
10        boolean hasConsonant = false;
11      
12        // Create a lookup table for vowels (a, e, i, o, u)
13        boolean[] isVowelLookup = new boolean[26];
14        for (char vowel : "aeiou".toCharArray()) {
15            isVowelLookup[vowel - 'a'] = true;
16        }
17      
18        // Iterate through each character in the word
19        for (char currentChar : word.toCharArray()) {
20            if (Character.isAlphabetic(currentChar)) {
21                // For alphabetic characters, check if vowel or consonant
22                char lowercaseChar = Character.toLowerCase(currentChar);
23                int alphabetIndex = lowercaseChar - 'a';
24              
25                if (isVowelLookup[alphabetIndex]) {
26                    hasVowel = true;
27                } else {
28                    hasConsonant = true;
29                }
30            } else if (!Character.isDigit(currentChar)) {
31                // If character is neither alphabetic nor digit, word is invalid
32                return false;
33            }
34            // Digits are allowed but don't affect vowel/consonant requirements
35        }
36      
37        // Word is valid only if it contains at least one vowel AND one consonant
38        return hasVowel && hasConsonant;
39    }
40}
41
1class Solution {
2public:
3    bool isValid(string word) {
4        // Check minimum length requirement
5        if (word.size() < 3) {
6            return false;
7        }
8      
9        // Initialize flags to track presence of vowels and consonants
10        bool hasVowel = false;
11        bool hasConsonant = false;
12      
13        // Create a lookup table for vowels (26 letters, indexed by 'a' to 'z')
14        bool isVowelLookup[26] = {};
15        string vowels = "aeiou";
16      
17        // Mark vowel positions in the lookup table
18        for (char c : vowels) {
19            isVowelLookup[c - 'a'] = true;
20        }
21      
22        // Iterate through each character in the word
23        for (char c : word) {
24            if (isalpha(c)) {
25                // Convert to lowercase and check if it's a vowel
26                char lowerChar = tolower(c);
27                if (isVowelLookup[lowerChar - 'a']) {
28                    hasVowel = true;
29                } else {
30                    hasConsonant = true;
31                }
32            } else if (!isdigit(c)) {
33                // If character is neither letter nor digit, word is invalid
34                return false;
35            }
36            // If character is a digit, continue to next character
37        }
38      
39        // Word is valid only if it contains at least one vowel and one consonant
40        return hasVowel && hasConsonant;
41    }
42};
43
1/**
2 * Validates if a word meets specific criteria:
3 * - Must be at least 3 characters long
4 * - Must contain only alphanumeric characters
5 * - Must contain at least one vowel
6 * - Must contain at least one consonant
7 * @param word - The word to validate
8 * @returns true if the word is valid, false otherwise
9 */
10function isValid(word: string): boolean {
11    // Check minimum length requirement
12    if (word.length < 3) {
13        return false;
14    }
15  
16    // Track whether vowel and consonant are found
17    let hasVowel: boolean = false;
18    let hasConsonant: boolean = false;
19  
20    // Define set of vowels (both lowercase and uppercase)
21    const vowels: Set<string> = new Set<string>(['a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U']);
22  
23    // Iterate through each character in the word
24    for (const character of word) {
25        // Check if character is alphanumeric
26        if (!/[a-zA-Z0-9]/.test(character)) {
27            return false;
28        }
29      
30        // If character is a letter, check if it's a vowel or consonant
31        if (/[a-zA-Z]/.test(character)) {
32            if (vowels.has(character)) {
33                hasVowel = true;
34            } else {
35                hasConsonant = true;
36            }
37        }
38    }
39  
40    // Word is valid only if it contains both vowel and consonant
41    return hasVowel && hasConsonant;
42}
43

Time and Space Complexity

The time complexity is O(n), where n is the length of the input string word. This is because the algorithm iterates through each character in the string exactly once using a single for loop. Within the loop, all operations are constant time: checking if a character is alphanumeric (isalnum()), checking if it's alphabetic (isalpha()), and checking membership in the vowel set are all O(1) operations.

The space complexity is O(1). The algorithm uses a fixed amount of extra space regardless of the input size. The vowel set vs contains exactly 10 characters (the vowels in both lowercase and uppercase), which is a constant. The boolean variables has_vowel and has_consonant also use constant space. No additional data structures that scale with the input size are created.

Learn more about how to find time and space complexity quickly.

Common Pitfalls

1. Forgetting that digits are neither vowels nor consonants

A common mistake is assuming that if a character is not a vowel, it must be a consonant. This leads to incorrectly counting digits as consonants.

Incorrect approach:

for char in word:
    if not char.isalnum():
        return False
    if char in vowels:
        has_vowel = True
    else:  # Wrong! This treats digits as consonants
        has_consonant = True

Correct approach:

for char in word:
    if not char.isalnum():
        return False
    if char.isalpha():  # Only check letters for vowel/consonant
        if char in vowels:
            has_vowel = True
        else:
            has_consonant = True

2. Case sensitivity issues with vowel checking

Developers often forget to check both uppercase and lowercase vowels, leading to words like "ABC" being incorrectly validated.

Incorrect approach:

vowels = set("aeiou")  # Missing uppercase vowels

Correct approach:

vowels = set("aeiouAEIOU")  # Include both cases
# OR
if char.lower() in "aeiou":  # Convert to lowercase for comparison

3. Early return optimization mistake

Some might try to optimize by returning true as soon as both conditions are met, but forget to complete the character validation.

Incorrect approach:

for char in word:
    if char.isalpha():
        if char in vowels:
            has_vowel = True
        else:
            has_consonant = True
        if has_vowel and has_consonant:
            return True  # Wrong! Haven't checked all characters for validity
    # Missing check for invalid characters

Correct approach:

for char in word:
    if not char.isalnum():
        return False  # Must validate all characters first
    if char.isalpha():
        if char in vowels:
            has_vowel = True
        else:
            has_consonant = True
return has_vowel and has_consonant

4. Misunderstanding alphanumeric validation

Using incorrect methods to check for valid characters, such as checking against a predefined string instead of using isalnum().

Incorrect approach:

valid_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
for char in word:
    if char not in valid_chars:  # Inefficient O(n) lookup
        return False

Correct approach:

for char in word:
    if not char.isalnum():  # Built-in method, O(1) check
        return False
Discover Your Strengths and Weaknesses: Take Our 3-Minute Quiz to Tailor Your Study Plan:

What is an advantages of top-down dynamic programming vs bottom-up dynamic programming?


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More