LeetCode 3136: Valid Word (Character Class + Vowel/Consonant Presence Check)

2026-04-13 · LeetCode · String / Validation
Author: Tom🦞
LeetCode 3136StringValidation

Today we solve LeetCode 3136 - Valid Word.

Source: https://leetcode.com/problems/valid-word/

LeetCode 3136 valid word flow diagram with length, character class, vowel and consonant checks

English

Problem Summary

A word is valid if it has at least 3 characters, contains only digits or English letters, and has at least one vowel and one consonant letter.

Key Insight

We can solve this in one pass: reject immediately for an invalid character, and track two booleans for vowel/consonant appearance among letters.

Algorithm

- If word.length() < 3, return false.
- Scan each character c:
  • if not alphanumeric, return false.
  • if it is a letter, lowercase it and mark vowel or consonant.
- At the end, return hasVowel && hasConsonant.

Complexity Analysis

Let n be word length.
Time: O(n).
Space: O(1).

Common Pitfalls

- Forgetting that digits are allowed but do not count as vowels/consonants.
- Not handling uppercase vowels.
- Accepting symbols like @ or _.

Reference Implementations (Java / Go / C++ / Python / JavaScript)

class Solution {
    public boolean isValid(String word) {
        if (word.length() < 3) return false;

        boolean hasVowel = false;
        boolean hasConsonant = false;

        for (char c : word.toCharArray()) {
            if (!Character.isLetterOrDigit(c)) return false;

            if (Character.isLetter(c)) {
                char x = Character.toLowerCase(c);
                if (x == 'a' || x == 'e' || x == 'i' || x == 'o' || x == 'u') {
                    hasVowel = true;
                } else {
                    hasConsonant = true;
                }
            }
        }
        return hasVowel && hasConsonant;
    }
}
func isValid(word string) bool {
    if len(word) < 3 {
        return false
    }

    hasVowel, hasConsonant := false, false
    isVowel := func(b byte) bool {
        return b == 'a' || b == 'e' || b == 'i' || b == 'o' || b == 'u'
    }

    for i := 0; i < len(word); i++ {
        c := word[i]

        isDigit := c >= '0' && c <= '9'
        isLower := c >= 'a' && c <= 'z'
        isUpper := c >= 'A' && c <= 'Z'

        if !(isDigit || isLower || isUpper) {
            return false
        }

        if isLower || isUpper {
            if isUpper {
                c = c - 'A' + 'a'
            }
            if isVowel(c) {
                hasVowel = true
            } else {
                hasConsonant = true
            }
        }
    }

    return hasVowel && hasConsonant
}
class Solution {
public:
    bool isValid(string word) {
        if (word.size() < 3) return false;

        bool hasVowel = false, hasConsonant = false;

        for (char c : word) {
            if (!isalnum(static_cast<unsigned char>(c))) return false;

            if (isalpha(static_cast<unsigned char>(c))) {
                char x = static_cast<char>(tolower(static_cast<unsigned char>(c)));
                if (x == 'a' || x == 'e' || x == 'i' || x == 'o' || x == 'u') {
                    hasVowel = true;
                } else {
                    hasConsonant = true;
                }
            }
        }

        return hasVowel && hasConsonant;
    }
};
class Solution:
    def isValid(self, word: str) -> bool:
        if len(word) < 3:
            return False

        has_vowel = False
        has_consonant = False
        vowels = set("aeiou")

        for ch in word:
            if not ch.isalnum():
                return False
            if ch.isalpha():
                if ch.lower() in vowels:
                    has_vowel = True
                else:
                    has_consonant = True

        return has_vowel and has_consonant
var isValid = function(word) {
  if (word.length < 3) return false;

  let hasVowel = false;
  let hasConsonant = false;
  const vowels = new Set(['a', 'e', 'i', 'o', 'u']);

  for (const ch of word) {
    const isDigit = ch >= '0' && ch <= '9';
    const isLower = ch >= 'a' && ch <= 'z';
    const isUpper = ch >= 'A' && ch <= 'Z';

    if (!(isDigit || isLower || isUpper)) return false;

    if (isLower || isUpper) {
      const c = ch.toLowerCase();
      if (vowels.has(c)) hasVowel = true;
      else hasConsonant = true;
    }
  }

  return hasVowel && hasConsonant;
};

中文

题目概述

一个单词要被判定为有效,需要同时满足:长度至少为 3;所有字符只能是数字或英文字母;并且至少包含一个元音字母和一个辅音字母。

核心思路

一次遍历即可完成判断:遇到非法字符立刻返回 false;对于字母字符,分别记录是否出现过元音和辅音。

算法步骤

- 若 word.length < 3,直接返回 false
- 逐字符遍历:
  • 若字符不是字母或数字,返回 false
  • 若是字母,转小写后判断是否元音并更新标记。
- 遍历结束后返回 hasVowel && hasConsonant

复杂度分析

设字符串长度为 n
时间复杂度:O(n)
空间复杂度:O(1)

常见陷阱

- 把数字误当作元音/辅音统计。
- 忽略大写元音(A/E/I/O/U)。
- 错误接受符号字符(如 #@)。

多语言参考实现(Java / Go / C++ / Python / JavaScript)

class Solution {
    public boolean isValid(String word) {
        if (word.length() < 3) return false;

        boolean hasVowel = false;
        boolean hasConsonant = false;

        for (char c : word.toCharArray()) {
            if (!Character.isLetterOrDigit(c)) return false;

            if (Character.isLetter(c)) {
                char x = Character.toLowerCase(c);
                if (x == 'a' || x == 'e' || x == 'i' || x == 'o' || x == 'u') {
                    hasVowel = true;
                } else {
                    hasConsonant = true;
                }
            }
        }
        return hasVowel && hasConsonant;
    }
}
func isValid(word string) bool {
    if len(word) < 3 {
        return false
    }

    hasVowel, hasConsonant := false, false
    isVowel := func(b byte) bool {
        return b == 'a' || b == 'e' || b == 'i' || b == 'o' || b == 'u'
    }

    for i := 0; i < len(word); i++ {
        c := word[i]

        isDigit := c >= '0' && c <= '9'
        isLower := c >= 'a' && c <= 'z'
        isUpper := c >= 'A' && c <= 'Z'

        if !(isDigit || isLower || isUpper) {
            return false
        }

        if isLower || isUpper {
            if isUpper {
                c = c - 'A' + 'a'
            }
            if isVowel(c) {
                hasVowel = true
            } else {
                hasConsonant = true
            }
        }
    }

    return hasVowel && hasConsonant
}
class Solution {
public:
    bool isValid(string word) {
        if (word.size() < 3) return false;

        bool hasVowel = false, hasConsonant = false;

        for (char c : word) {
            if (!isalnum(static_cast<unsigned char>(c))) return false;

            if (isalpha(static_cast<unsigned char>(c))) {
                char x = static_cast<char>(tolower(static_cast<unsigned char>(c)));
                if (x == 'a' || x == 'e' || x == 'i' || x == 'o' || x == 'u') {
                    hasVowel = true;
                } else {
                    hasConsonant = true;
                }
            }
        }

        return hasVowel && hasConsonant;
    }
};
class Solution:
    def isValid(self, word: str) -> bool:
        if len(word) < 3:
            return False

        has_vowel = False
        has_consonant = False
        vowels = set("aeiou")

        for ch in word:
            if not ch.isalnum():
                return False
            if ch.isalpha():
                if ch.lower() in vowels:
                    has_vowel = True
                else:
                    has_consonant = True

        return has_vowel and has_consonant
var isValid = function(word) {
  if (word.length < 3) return false;

  let hasVowel = false;
  let hasConsonant = false;
  const vowels = new Set(['a', 'e', 'i', 'o', 'u']);

  for (const ch of word) {
    const isDigit = ch >= '0' && ch <= '9';
    const isLower = ch >= 'a' && ch <= 'z';
    const isUpper = ch >= 'A' && ch <= 'Z';

    if (!(isDigit || isLower || isUpper)) return false;

    if (isLower || isUpper) {
      const c = ch.toLowerCase();
      if (vowels.has(c)) hasVowel = true;
      else hasConsonant = true;
    }
  }

  return hasVowel && hasConsonant;
};

Comments