Bird
Raised Fist0
Interview Prepsubsets-combinationsmediumAmazonGoogleFacebook

Letter Case Permutation

Choose your preparation mode4 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Steps
setup

Initialize / Setup

The input string 'a1b2' is converted into a character array ['a', '1', 'b', '2']. The results list is initialized empty. The backtracking starts at index 0.

💡 Converting to a character array allows in-place modification of letters, which is efficient for exploring case permutations.
Line:res = [] arr = list(s) backtrack(0)
💡 Setup prepares the data structures and starts the recursive exploration from the first character.
📊
Letter Case Permutation - Watch the Algorithm Execute, Step by Step
Watching this step-by-step recursion tree is the fastest way to understand how backtracking explores all letter case combinations systematically and how the algorithm reverts changes to explore alternative paths.
Step 1/16
·Active fillAnswer cell
enteringi=0
Call Path (current → root)
backtrack(0)
Remaining
lowercase or uppercase for 'a'
enteringi=1
Call Path (current → root)
backtrack(1)
backtrack(0)
Remaining
digit skip at index 1
Partial: [a]
enteringi=2
Call Path (current → root)
backtrack(2)
backtrack(1)
backtrack(0)
Remaining
lowercase or uppercase for 'b'
Partial: [a, 1]
enteringi=3
Call Path (current → root)
backtrack(3)
backtrack(2)
backtrack(1)
backtrack(0)
Remaining
digit skip at index 3
Partial: [a, 1, b]
enteringi=4
Call Path (current → root)
backtrack(4)
backtrack(3)
backtrack(2)
backtrack(1)
backtrack(0)
Partial: [a, 1, b, 2]
backtrackingi=4
Call Path (current → root)
backtrack(4)
backtrack(3)
backtrack(2)
backtrack(1)
backtrack(0)
Partial: [a, 1, b, 2]
Found 1: [a1b2]
enteringi=4
Call Path (current → root)
backtrack(4)
backtrack(3)
backtrack(2)
backtrack(1)
backtrack(0)
Tried
lowercase
Remaining
uppercase
Partial: [a, 1, B, 2]
Found 1: [a1b2]
backtrackingi=4
Call Path (current → root)
backtrack(4)
backtrack(3)
backtrack(2)
backtrack(1)
backtrack(0)
Tried
lowercaseuppercase
Partial: [a, 1, B, 2]
Found 2: [a1b2] [a1B2]
enteringi=1
Call Path (current → root)
backtrack(1)
backtrack(0)
Tried
lowercase
Remaining
uppercase
Partial: [A]
Found 2: [a1b2] [a1B2]
enteringi=2
Call Path (current → root)
backtrack(2)
backtrack(1)
backtrack(0)
Remaining
lowercase or uppercase for 'b'
Partial: [A, 1]
Found 2: [a1b2] [a1B2]
enteringi=3
Call Path (current → root)
backtrack(3)
backtrack(2)
backtrack(1)
backtrack(0)
Remaining
digit skip at index 3
Partial: [A, 1, b]
Found 2: [a1b2] [a1B2]
enteringi=4
Call Path (current → root)
backtrack(4)
backtrack(3)
backtrack(2)
backtrack(1)
backtrack(0)
Partial: [A, 1, b, 2]
Found 2: [a1b2] [a1B2]
backtrackingi=4
Call Path (current → root)
backtrack(4)
backtrack(3)
backtrack(2)
backtrack(1)
backtrack(0)
Partial: [A, 1, b, 2]
Found 3: [a1B2] [A1b2]
enteringi=4
Call Path (current → root)
backtrack(4)
backtrack(3)
backtrack(2)
backtrack(1)
backtrack(0)
Tried
lowercase
Remaining
uppercase
Partial: [A, 1, B, 2]
Found 3: [a1B2] [A1b2]
backtrackingi=4
Call Path (current → root)
backtrack(4)
backtrack(3)
backtrack(2)
backtrack(1)
backtrack(0)
Tried
lowercaseuppercase
Partial: [A, 1, B, 2]
Found 4: [A1b2] [A1B2]
backtrackingi=0
Call Path (current → root)
backtrack(0)
Tried
lowercaseuppercase
Found 4: [A1b2] [A1B2]

Key Takeaways

Backtracking explores all letter case permutations by branching at each letter and skipping digits.

This insight is hard to see from code alone because the recursion and branching are implicit; visualization makes the branching explicit.

Digits do not increase the recursion tree's branching factor and are efficiently skipped.

Understanding how digits simplify the recursion helps grasp the algorithm's efficiency.

Backtracking reverts changes to explore alternative branches cleanly, ensuring all permutations are generated without corrupting state.

The importance of reverting state is subtle in code but critical for correctness; visualization shows this clearly.

Practice

(1/5)
1. Consider the following code snippet implementing the trie-based solution for counting valid words for puzzles. Given the words = ["apple", "plea", "plead"] and puzzles = ["aelwxyz"], what is the returned count for this puzzle?
easy
A. [1]
B. [0]
C. [2]
D. [3]

Solution

  1. Step 1: Compute bitmasks for words

    "apple" -> letters {a,p,l,e}, mask with ≤7 bits; "plea" and "plead" similarly processed.
  2. Step 2: Check puzzle "aelwxyz"

    First letter 'a' must be in word; words "apple" and "plea" contain 'a' and are subsets of puzzle letters; "plead" contains 'd' not in puzzle.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Two words match conditions [OK]
Hint: Count words containing puzzle first letter and subset of puzzle letters [OK]
Common Mistakes:
  • Counting words missing first letter
  • Including words with letters outside puzzle
  • Off-by-one in counting matches
2. You need to generate all possible subsets of a given set of distinct integers. Which algorithmic approach guarantees enumerating every subset exactly once, including the empty subset, without missing or duplicating any subset?
easy
A. Greedy algorithm that picks elements based on a heuristic to maximize subset size
B. Dynamic programming approach that builds subsets by summing elements to target values
C. Backtracking with include/exclude decisions at each element to explore all subset combinations
D. Sorting the array and then using two pointers to find pairs that form subsets

Solution

  1. Step 1: Understand problem requirements

    The problem requires enumerating all subsets, which means exploring all combinations of including or excluding each element.
  2. Step 2: Identify suitable algorithm

    Backtracking with include/exclude decisions systematically explores all subsets without duplication or omission, including the empty subset.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Backtracking ensures all subsets are generated [OK]
Hint: Include/exclude backtracking covers all subsets [OK]
Common Mistakes:
  • Confusing subset generation with greedy or DP sum problems
3. Consider the following Python code that generates all subsets of nums = [1, 2, 3]. What is the value of subset when mask = 5 during the iteration?
easy
A. [1, 3]
B. [2, 3]
C. [1, 2]
D. [3]

Solution

  1. Step 1: Convert mask=5 to binary

    5 in binary is 101, meaning bits 0 and 2 are set.
  2. Step 2: Map bits to indices in nums

    Bit 0 corresponds to nums[0]=1, bit 2 corresponds to nums[2]=3, so subset = [1, 3].
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Mask 5 selects elements at positions 0 and 2 -> [1, 3] [OK]
Hint: Mask bits correspond to included elements [OK]
Common Mistakes:
  • Off-by-one bit indexing
  • Confusing mask bits with element values
4. What is the time complexity of the iterative lexicographic combinations generation algorithm for generating all combinations of size k from n elements?
medium
A. O(n^k) because each element can be chosen or not
B. O(k * (n choose k)) since each combination of size k is generated once and updated in O(k)
C. O(\u03C3(n choose k) * k) where \u03C3 is the number of combinations generated
D. O(n * k) because the outer loop runs n times and inner loop k times

Solution

  1. Step 1: Identify number of combinations

    There are exactly (n choose k) combinations to generate.
  2. Step 2: Analyze per-combination cost

    Each combination is generated and updated in O(k) time due to copying and resetting elements.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Time is proportional to number of combinations times combination size [OK]
Hint: Time depends on number of combinations times k [OK]
Common Mistakes:
  • Confusing with exponential O(n^k) or linear O(n*k) complexities
5. Suppose the problem is modified so that each element in the array can be used multiple times to form the k equal sum subsets (i.e., unlimited reuse of elements). Which modification to the backtracking with bitmask memoization approach is necessary to correctly solve this variant?
hard
A. Keep bitmask but allow resetting bits after each recursive call
B. Sort ascending instead of descending to handle reuse properly
C. Use the same code without changes because bitmask handles reuse implicitly
D. Remove bitmask usage since elements can be reused; track counts instead

Solution

  1. Step 1: Understand reuse impact on state representation

    Bitmask tracks used elements uniquely; with reuse allowed, usage state is not binary but counts.
  2. Step 2: Modify approach accordingly

    Bitmask must be removed or replaced by frequency counts to track how many times each element is used; otherwise, states are incorrect.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Bitmask cannot represent multiple uses of same element [OK]
Hint: Bitmask tracks usage once; reuse breaks this assumption [OK]
Common Mistakes:
  • Trying to reuse bitmask for multiple uses
  • Ignoring state representation changes