↓Skip to main content
  1. LeetCode/

LeetCode 1178: Number of Valid Words for Each Puzzle

·3 mins· ·
LeetCode Hard Bit-Manipulation Hash-Map Trie
Wei Yi Chung
Author
Wei Yi Chung
Working at the contributing of open source, distributed systems, and data engineering.
Table of Contents

Meta Data
#

Difficulty: hard First Attempt: 2026-08-28

  • Submissions: Accepted (first try)

Approach
#

A word is valid for a puzzle when:

  1. It contains the puzzle’s first letter.
  2. Every letter of the word appears in the puzzle.

Both conditions depend only on which letters are used, not their order or counts. So each word compresses to a 26-bit mask, and a Counter records how many words have each mask.

Each puzzle has exactly 7 letters, so:

  • A valid word’s mask is “a subset of the puzzle mask that includes the first letter”.
  • Apart from the first letter, the other 6 letters have only 2^6 = 64 subsets.

For each puzzle, enumerate those 64 subsets, add the first letter, and sum the Counter lookups.

Enumerating subsets
#

sub = mask
while True:
    process(sub)
    if sub == 0:
        break
    sub = (sub - 1) & mask

(sub - 1) & mask walks through every subset of mask from largest to smallest, ending at 0.

My Solution
#

from collections import Counter

class Solution:
    def findNumOfValidWords(self, words: List[str], puzzles: List[str]) -> List[int]:
        def to_mask(s: str) -> int:
            m = 0
            for ch in s:
                m |= 1 << (ord(ch) - ord("a"))
            return m

        word_count = Counter(to_mask(w) for w in words)

        res = []
        for p in puzzles:
            first = 1 << (ord(p[0]) - ord("a"))
            rest = to_mask(p[1:])
            count = 0
            sub = rest
            while True:
                count += word_count[sub | first]
                if sub == 0:
                    break
                sub = (sub - 1) & rest
            res.append(count)
        return res

Separating the first letter and enumerating subsets of the other 6 letters, then OR-ing in first, guarantees every mask includes the first letter.

Complexity
#

Time O(W + P · 2^6), where W is the total length of all words and P the number of puzzles. Space O(number of words).

Mistakes to Avoid
#

  • Checking every word against every puzzle: 10^5 × 10^4 is too slow.
  • Including the first letter in the enumerated subsets: masks without it get enumerated too.
  • Skipping the empty subset: a word using only the first letter (e.g. "aaaa") is found through the empty subset plus first.

Interview Explanation
#

Validity depends only on the set of letters a word uses, so I convert each word to a 26-bit mask and count them. A puzzle has 7 letters, and a valid word’s mask must be a subset of the puzzle’s mask that includes the first letter, so I enumerate the 64 subsets of the other 6 letters, add the first letter, and look each up in the counter. Time O(W + 64P). LeetCode tags it as Trie, but bitmasks are more direct.

Related

LeetCode 3910: Count Connected Subgraphs with Even Node Sum
·3 mins
LeetCode Hard Bit-Manipulation Enumeration Graph Union-Find
LeetCode 3910 note: n is tiny, so enumerate subsets with a bitmask, check the even sum first, then check that the induced subgraph is connected
LeetCode 726: Number of Atoms
·3 mins
LeetCode Hard Stack String Hash-Map Sorting
LeetCode 726 note: tokenize into elements, numbers, and parentheses; handle parentheses with a stack, with a default multiplier of 1
LeetCode 2781: Length of the Longest Valid Substring
·3 mins
LeetCode Hard Sliding-Window Hash-Table String Trie
LeetCode 2781 note: forbidden words are at most 10 long, so each right end checks only the last 10 suffixes; on a match push the left end past it, using the shortest match (the rightmost start)
LeetCode 30: Substring with Concatenation of All Words (Brute Force → Counting → Sliding Window)
·3 mins
LeetCode Daily Hard String Sliding-Window Two-Pointers Hash-Map Brute-Force Frequency-Counting
Three approaches: brute force, counting optimization, and sliding window over word-length offsets.
LeetCode 76: Minimum Window Substring
·3 mins
LeetCode Daily Hard String Sliding-Window Variable-Window Two-Pointers Hash-Map
LeetCode Problem Solving - Variable Size Sliding Window with Character Counting
LeetCode 2585: Number of Ways to Earn Points
·2 mins
LeetCode Hard Dynamic-Programming Knapsack Array
LeetCode 2585 note: a bounded (grouped) knapsack; each question type takes 0 to count questions, with capacity running backwards and the count enumerated inside