Bird
Raised Fist0
Interview PrepbacktrackinghardAmazonFacebookGoogleBloomberg

Word Search II (Trie + Backtrack)

Choose your preparation mode4 modes available
▶
Steps
setup

Build Trie - insert 'eat'

Insert word 'eat' into the trie. Root → e(id=1) → a(id=2) → t(id=3, word='eat'). Three nodes created along the path.

💡 The trie stores all search words as paths from root. Each character gets its own node.
Line:for w in words: node = root for c in w: if c not in node.children: node.children[c] = TrieNode() node = node.children[c] node.word = w
💡 Inserting 'eat' creates nodes for e→a→t with word='eat' at the leaf.
📊
Word Search II - Watch the Trie + Backtracking Execute, Step by Step
The trie acts as a combined dictionary and prefix checker - instead of checking all words per cell, we follow one trie path that matches the board. When the trie has no child for a board character we prune immediately.
Step 1/11
·Active fill★Answer cell
insert
eat
◉eat*
insert
oath
◉eoath*
search
t
◉
Search: false
search
e
◉e
search
ea
◉ea
search
e
◉e
search
eat
◉eat*
Pairs found: 1
Search: true
search
o
◉o
Pairs found: 1
search
oa
◉oa
Pairs found: 1
search
oat
◉oat
Pairs found: 1
find_pairs
oath
◉oh*
Pairs found: 2
Search: true

Key Takeaways

✓ Building a trie from all words allows prefix-based pruning - if no word starts with a board character the DFS is skipped entirely.

Without a trie you'd check each word against each board path separately, which is much slower.

✓ Marking cells '#' during DFS prevents revisiting the same cell in one path, ensuring valid board paths only.

The restore step (board[r][c] = letter) after backtracking lets other DFS paths reuse the cell.

✓ Pruning trie nodes with no children after finding a word avoids re-finding the same word and shrinks future search space.

This optimization is subtle but powerful - the trie gets smaller as words are found.

Practice

(1/5)
1. Consider the following Python code snippet implementing the optimal backtracking approach for Expression Add Operators. Given input num = "123" and target = 6, what is the content of the result list after the function completes?
from typing import List

def addOperators(num: str, target: int) -> List[str]:
    res = []
    path = []
    def backtrack(index: int, evaluated: int, last_operand: int):
        if index == len(num):
            if evaluated == target:
                res.append(''.join(path))
            return
        for i in range(index, len(num)):
            if i != index and num[index] == '0':
                break
            curr_str = num[index:i+1]
            curr = int(curr_str)
            length_before = len(path)
            if index == 0:
                path.append(curr_str)
                backtrack(i+1, curr, curr)
                path[length_before:] = []
            else:
                path.append('+'); path.append(curr_str)
                backtrack(i+1, evaluated + curr, curr)
                path[length_before:] = []
    backtrack(0, 0, 0)
    return res
easy
A. ["1+23", "12+3"]
B. ["123"]
C. ["1+2+3", "123"]
D. ["1+2+3"]

Solution

  1. Step 1: Trace backtracking calls for num="123", target=6

    At index=0, path starts with "1". Then at index=1, add '+' and "2", evaluated=3. Then at index=2, add '+' and "3", evaluated=6, matches target, so "1+2+3" is added.
  2. Step 2: Check other possible expressions

    "123" alone evaluates to 123, not 6. "1+23"=24, "12+3"=15, none equal 6. So only "1+2+3" is in result.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Only "1+2+3" sums to 6 [OK]
Hint: Only "1+2+3" equals 6 with given operators [OK]
Common Mistakes:
  • Assuming "123" or "1+23" equals target
2. Consider the following buggy code for generating letter combinations. Which line contains the subtle bug that causes incorrect or incomplete results?
from collections import deque

def letterCombinations(digits):
    if digits == '':
        return ['']
    digit_map = {'2': 'abc', '3': 'def', '4': 'ghi', '5': 'jkl',
                 '6': 'mno', '7': 'pqrs', '8': 'tuv', '9': 'wxyz'}
    queue = deque([''])
    for digit in digits:
        letters = digit_map[digit]
        for _ in range(len(queue)):
            prev = queue.popleft()
            for char in letters:
                queue.append(prev + char)
    return list(queue)
medium
A. Line 7: letters = digit_map[digit]
B. Line 2: if digits == '': return ['']
C. Line 10: prev = queue.popleft()
D. Line 1: from collections import deque

Solution

  1. Step 1: Analyze empty input handling

    Returning [''] for empty input is incorrect; the problem expects an empty list [] when input is empty.
  2. Step 2: Check other lines

    Digit mapping, queue operations, and imports are correct and do not cause bugs.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Empty input should return [] not [''] to match problem spec [OK]
Hint: Empty input must return empty list, not list with empty string [OK]
Common Mistakes:
  • Returning [''] instead of [] for empty input
  • Assuming digits '1' or '0' map to letters
3. Suppose the N-Queens problem is modified so that queens can be placed multiple times in the same column (i.e., column constraint is relaxed), but diagonal attacks still apply. Which modification to the bitmask backtracking algorithm correctly adapts to this variant?
hard
A. Remove the column bitmask tracking and only track diagonal attacks in recursion
B. Keep column bitmask but allow multiple queens by resetting it each row
C. Use a greedy approach placing queens in any column without pruning
D. Track columns as before but ignore diagonal bitmasks

Solution

  1. Step 1: Understand relaxed constraints

    Since columns can have multiple queens, column bitmask is no longer needed to prune placements.
  2. Step 2: Adapt pruning to only diagonal attacks

    Keep diag1 and diag2 bitmasks to prune diagonal conflicts, but remove column mask from available_positions calculation.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Removing column mask allows multiple queens per column while still pruning diagonals [OK]
Hint: Relaxed constraints remove column pruning, keep diagonal pruning [OK]
Common Mistakes:
  • Resetting column mask each row incorrectly
  • Ignoring diagonal pruning
  • Using greedy without pruning
4. Suppose you want to modify the palindrome partitioning algorithm to allow reuse of substrings in partitions (i.e., substrings can appear multiple times in different partitions). Which change to the algorithm is necessary to correctly handle this variant without losing valid partitions or causing duplicates?
hard
A. Memoize palindrome checks and reuse results but keep backtracking unchanged
B. Modify backtracking to avoid popping from path to reuse substrings across calls
C. Use a global visited set to skip substrings already used in previous partitions
D. Allow substrings to be reused by resetting path after each complete partition

Solution

  1. Step 1: Understand reuse requirement

    Reusing substrings means substrings can appear multiple times in different partitions, so path management must allow multiple uses.
  2. Step 2: Identify necessary algorithm change

    Memoizing palindrome checks improves efficiency by avoiding repeated palindrome computations, while backtracking logic remains unchanged to generate all valid partitions.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Memoization optimizes palindrome checks without affecting partition generation correctness [OK]
Hint: Memoize palindrome checks to optimize without changing backtracking [OK]
Common Mistakes:
  • Assuming popping affects substring reuse
  • Using visited sets that block valid reuse
  • Resetting path incorrectly losing partitions
5. Suppose you want to generate all permutations of an array where elements can be repeated any number of times (i.e., unlimited reuse of elements). Which modification to the standard backtracking approach is correct?
hard
A. Remove the used array entirely and allow elements to be chosen multiple times at each recursion level
B. Use the same backtracking with a used array but reset used[i] to false only after the entire recursion finishes
C. Use in-place swapping but skip swapping elements that have been used before in the current recursion path
D. Generate permutations normally and then filter out duplicates after generation

Solution

  1. Step 1: Understand the problem variant

    Elements can be reused unlimited times, so no need to track usage.
  2. Step 2: Modify backtracking accordingly

    Removing the used array allows choosing any element at each recursion level multiple times, generating permutations with repetition.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Allowing repeated choices without usage tracking fits unlimited reuse [OK]
Hint: Unlimited reuse means no used array needed [OK]
Common Mistakes:
  • Keeping used array causes missing permutations or incorrect pruning
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard