Number of Valid Words for Each Puzzle
HardUpdated: Aug 2, 2025
Practice on:
Problem
With respect to a given puzzle string, a word is valid if both the following conditions are satisfied:
wordcontains the first letter ofpuzzle.- For each letter in
word, that letter is inpuzzle. - For example, if the puzzle is
"abcdefg", then valid words are"faced","cabbage", and"baggage", while - invalid words are
"beefed"(does not include'a') and"based"(includes's'which is not in the puzzle).
Return an arrayanswer , whereanswer[i]is the number of words in the given word listwords that is valid with respect to the puzzlepuzzles[i].
Examples
Example 1
Input: words = ["aaaa","asas","able","ability","actt","actor","access"], puzzles = ["aboveyz","abrodyz","abslute","absoryz","actresz","gaswxyz"]
Output: [1,1,3,2,4,0]
Explanation:
1 valid word for "aboveyz" : "aaaa"
1 valid word for "abrodyz" : "aaaa"
3 valid words for "abslute" : "aaaa", "asas", "able"
2 valid words for "absoryz" : "aaaa", "asas"
4 valid words for "actresz" : "aaaa", "asas", "actt", "access"
There are no valid words for "gaswxyz" cause none of the words in the list contains letter 'g'.
Example 2
Input: words = ["apple","pleas","please"], puzzles = ["aelwxyz","aelpxyz","aelpsxy","saelpxy","xaelpsy"]
Output: [0,1,3,2,0]
Constraints
1 <= words.length <= 10^54 <= words[i].length <= 501 <= puzzles.length <= 10^4puzzles[i].length == 7words[i]andpuzzles[i]consist of lowercase English letters.- Each
puzzles[i]does not contain repeated characters.
Solution
Method 1 – Bitmasking and Hash Map
Intuition
Each word and puzzle can be represented as a bitmask. For each puzzle, enumerate all its subsets that include the first letter, and count how many words have the same bitmask.
Approach
- For each word, compute its bitmask and count the frequency in a hash map.
- For each puzzle, enumerate all subsets of its letters that include the first letter (using bitmask subset enumeration).
- For each subset, add the count from the hash map to the answer for that puzzle.
- Return the answer array.
Code
C++
class Solution {
public:
vector<int> findNumOfValidWords(vector<string>& words, vector<string>& puzzles) {
unordered_map<int, int> freq;
for (auto& w : words) {
int mask = 0;
for (char c : w) mask |= 1 << (c - 'a');
freq[mask]++;
}
vector<int> ans;
for (auto& p : puzzles) {
int mask = 0;
for (char c : p) mask |= 1 << (c - 'a');
int first = 1 << (p[0] - 'a');
int sub = mask, cnt = 0;
do {
if (sub & first) cnt += freq[sub];
sub = (sub - 1) & mask;
} while (sub != mask);
ans.push_back(cnt);
}
return ans;
}
};
Go
func findNumOfValidWords(words []string, puzzles []string) []int {
freq := map[int]int{}
for _, w := range words {
mask := 0
for _, c := range w {
mask |= 1 << (c - 'a')
}
freq[mask]++
}
ans := make([]int, len(puzzles))
for i, p := range puzzles {
mask := 0
for _, c := range p {
mask |= 1 << (c - 'a')
}
first := 1 << (p[0] - 'a')
sub := mask
cnt := 0
for {
if sub&first != 0 {
cnt += freq[sub]
}
if sub == 0 { break }
sub = (sub - 1) & mask
}
ans[i] = cnt
}
return ans
}
Java
class Solution {
public List<Integer> findNumOfValidWords(String[] words, String[] puzzles) {
Map<Integer, Integer> freq = new HashMap<>();
for (String w : words) {
int mask = 0;
for (char c : w.toCharArray()) mask |= 1 << (c - 'a');
freq.put(mask, freq.getOrDefault(mask, 0) + 1);
}
List<Integer> ans = new ArrayList<>();
for (String p : puzzles) {
int mask = 0;
for (char c : p.toCharArray()) mask |= 1 << (c - 'a');
int first = 1 << (p.charAt(0) - 'a');
int sub = mask, cnt = 0;
do {
if ((sub & first) != 0) cnt += freq.getOrDefault(sub, 0);
sub = (sub - 1) & mask;
} while (sub != mask);
ans.add(cnt);
}
return ans;
}
}
Kotlin
class Solution {
fun findNumOfValidWords(words: Array<String>, puzzles: Array<String>): List<Int> {
val freq = mutableMapOf<Int, Int>()
for (w in words) {
var mask = 0
for (c in w) mask = mask or (1 shl (c - 'a'))
freq[mask] = freq.getOrDefault(mask, 0) + 1
}
val ans = mutableListOf<Int>()
for (p in puzzles) {
var mask = 0
for (c in p) mask = mask or (1 shl (c - 'a'))
val first = 1 shl (p[0] - 'a')
var sub = mask; var cnt = 0
do {
if ((sub and first) != 0) cnt += freq.getOrDefault(sub, 0)
sub = (sub - 1) and mask
} while (sub != mask)
ans.add(cnt)
}
return ans
}
}
Python
class Solution:
def findNumOfValidWords(self, words: list[str], puzzles: list[str]) -> list[int]:
from collections import Counter
freq = Counter()
for w in words:
mask = 0
for c in set(w):
mask |= 1 << (ord(c)-97)
freq[mask] += 1
ans = []
for p in puzzles:
mask = 0
for c in p:
mask |= 1 << (ord(c)-97)
first = 1 << (ord(p[0])-97)
sub = mask
cnt = 0
while True:
if sub & first:
cnt += freq[sub]
if sub == 0:
break
sub = (sub-1) & mask
ans.append(cnt)
return ans
Rust
use std::collections::HashMap;
impl Solution {
pub fn find_num_of_valid_words(words: Vec<String>, puzzles: Vec<String>) -> Vec<i32> {
let mut freq = HashMap::new();
for w in words.iter() {
let mut mask = 0;
for c in w.chars() { mask |= 1 << (c as u8 - b'a'); }
*freq.entry(mask).or_insert(0) += 1;
}
let mut ans = Vec::with_capacity(puzzles.len());
for p in puzzles.iter() {
let mut mask = 0;
for c in p.chars() { mask |= 1 << (c as u8 - b'a'); }
let first = 1 << (p.chars().next().unwrap() as u8 - b'a');
let mut sub = mask;
let mut cnt = 0;
loop {
if sub & first != 0 { cnt += *freq.get(&sub).unwrap_or(&0); }
if sub == 0 { break; }
sub = (sub-1) & mask;
}
ans.push(cnt);
}
ans
}
}
TypeScript
class Solution {
findNumOfValidWords(words: string[], puzzles: string[]): number[] {
const freq = new Map<number, number>()
for (const w of words) {
let mask = 0
for (const c of new Set(w)) mask |= 1 << (c.charCodeAt(0) - 97)
freq.set(mask, (freq.get(mask) || 0) + 1)
}
const ans: number[] = []
for (const p of puzzles) {
let mask = 0
for (const c of p) mask |= 1 << (c.charCodeAt(0) - 97)
const first = 1 << (p.charCodeAt(0) - 97)
let sub = mask, cnt = 0
do {
if (sub & first) cnt += freq.get(sub) || 0
sub = (sub - 1) & mask
} while (sub !== mask)
ans.push(cnt)
}
return ans
}
}
Complexity
- ⏰ Time complexity:
O(N + Q * 2^7), where N is the number of words and Q is the number of puzzles. - 🧺 Space complexity:
O(N), for the frequency map.