LeetCode 3136: Valid Word (Character Class + Vowel/Consonant Presence Check)
LeetCode 3136StringValidationToday we solve LeetCode 3136 - Valid Word.
Source: https://leetcode.com/problems/valid-word/
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_consonantvar 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_consonantvar 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