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
🎯
Letter Case Permutation
mediumBACKTRACKINGAmazonGoogleFacebook

Imagine you are designing a username generator that can create all possible variations of a string by toggling the case of its letters, helping users find unique but related usernames.

💡 This problem is about generating all possible variations of a string by changing letter cases. Beginners often struggle because it requires exploring multiple branching choices recursively, which can be confusing without a clear include/exclude mindset.
📋
Problem Statement

Given a string s, you can transform every letter individually to be lowercase or uppercase to create new strings. Return a list of all possible strings we could create. Digits remain unchanged.

1 ≤ s.length ≤ 12s consists of only letters or digits.
💡
Example
Input"a1b2"
Outputa1b2a1B2A1b2A1B2

For each letter, we choose lowercase or uppercase, digits stay the same. So 'a' → 'a' or 'A', 'b' → 'b' or 'B'.

  • Empty string → [] or [''] depending on interpretation
  • String with no letters (e.g., '1234') → ['1234'] only
  • String with all letters (e.g., 'abc') → all 2^3 = 8 permutations
  • String with mixed letters and digits (e.g., 'a1b') → permutations only change letters
⚠️
Common Mistakes
Not handling digits correctly

Digits get toggled or skipped incorrectly, leading to wrong outputs

Explicitly check if character is digit and only append without branching

Not backtracking properly (forgetting to revert changes)

Subsequent recursive calls use wrong characters, corrupting results

Always revert character or path changes after recursive calls

Using string concatenation in recursion without care

Leads to high memory usage and slower performance

Use character arrays or StringBuilder to optimize string building

Not considering empty string or all digits input

May return empty list or miss valid outputs

Handle edge cases explicitly and test them

🧠
Brute Force (Pure Recursion / Backtracking)
💡 This approach exists to build intuition on how to explore all possible choices by branching at each letter. It’s the foundation for understanding backtracking.

Intuition

At each character, if it's a letter, we branch into two recursive calls: one with lowercase and one with uppercase. If it's a digit, we only have one choice. We collect all results at the end.

Algorithm

  1. Start from index 0 and an empty path string.
  2. If current character is a digit, append it and recurse to next index.
  3. If current character is a letter, recurse twice: once with lowercase, once with uppercase appended.
  4. When index reaches string length, add the built path to results.
💡 The challenge is to remember to branch only on letters and to accumulate the path correctly through recursion.
</>
Code
from typing import List

def letterCasePermutation(s: str) -> List[str]:
    res = []
    def backtrack(i: int, path: List[str]):
        if i == len(s):
            res.append(''.join(path))
            return
        if s[i].isdigit():
            path.append(s[i])
            backtrack(i + 1, path)
            path.pop()
        else:
            path.append(s[i].lower())
            backtrack(i + 1, path)
            path.pop()
            path.append(s[i].upper())
            backtrack(i + 1, path)
            path.pop()
    backtrack(0, [])
    return res

# Driver code
if __name__ == '__main__':
    print(letterCasePermutation("a1b2"))
Line Notes
def letterCasePermutation(s: str) -> List[str]:Defines the main function with input string and output list of strings to return all permutations.
def backtrack(i: int, path: List[str]):Helper recursive function tracking current index and the path built so far to explore all branches.
if i == len(s):Base case: when index reaches end of string, join path and add to results as one valid permutation.
if s[i].isdigit():Digits do not branch; append digit and recurse to next index to maintain correctness.
path.append(s[i].lower())Try lowercase branch for current letter to explore one variation.
path.pop()Backtrack by removing last character to restore state before exploring next branch.
path.append(s[i].upper())Try uppercase branch for current letter to explore the other variation.
import java.util.*;

public class LetterCasePermutation {
    public static List<String> letterCasePermutation(String s) {
        List<String> res = new ArrayList<>();
        backtrack(s.toCharArray(), 0, new StringBuilder(), res);
        return res;
    }

    private static void backtrack(char[] chars, int i, StringBuilder path, List<String> res) {
        if (i == chars.length) {
            res.add(path.toString());
            return;
        }
        if (Character.isDigit(chars[i])) {
            path.append(chars[i]);
            backtrack(chars, i + 1, path, res);
            path.deleteCharAt(path.length() - 1);
        } else {
            path.append(Character.toLowerCase(chars[i]));
            backtrack(chars, i + 1, path, res);
            path.deleteCharAt(path.length() - 1);
            path.append(Character.toUpperCase(chars[i]));
            backtrack(chars, i + 1, path, res);
            path.deleteCharAt(path.length() - 1);
        }
    }

    public static void main(String[] args) {
        System.out.println(letterCasePermutation("a1b2"));
    }
}
Line Notes
public static List<String> letterCasePermutation(String s)Main function signature returning list of all permutations.
backtrack(s.toCharArray(), 0, new StringBuilder(), res);Start recursion with character array, index 0, empty path builder, and result list.
if (i == chars.length)Base case: when index reaches end, add current path string to results.
if (Character.isDigit(chars[i]))Digits do not branch; append digit and recurse to next index.
path.append(Character.toLowerCase(chars[i]));Try lowercase branch for current letter to explore one variation.
path.deleteCharAt(path.length() - 1);Backtrack by removing last appended character to restore state.
path.append(Character.toUpperCase(chars[i]));Try uppercase branch for current letter to explore the other variation.
#include <iostream>
#include <vector>
#include <string>
using namespace std;

class Solution {
public:
    vector<string> letterCasePermutation(string s) {
        vector<string> res;
        string path;
        backtrack(s, 0, path, res);
        return res;
    }

private:
    void backtrack(const string& s, int i, string& path, vector<string>& res) {
        if (i == s.size()) {
            res.push_back(path);
            return;
        }
        if (isdigit(s[i])) {
            path.push_back(s[i]);
            backtrack(s, i + 1, path, res);
            path.pop_back();
        } else {
            path.push_back(tolower(s[i]));
            backtrack(s, i + 1, path, res);
            path.pop_back();
            path.push_back(toupper(s[i]));
            backtrack(s, i + 1, path, res);
            path.pop_back();
        }
    }
};

int main() {
    Solution sol;
    vector<string> res = sol.letterCasePermutation("a1b2");
    for (auto& str : res) cout << str << endl;
    return 0;
}
Line Notes
vector<string> letterCasePermutation(string s)Main function returning vector of all permutations.
void backtrack(const string& s, int i, string& path, vector<string>& res)Recursive helper with current index and path string reference to build permutations.
if (i == s.size())Base case: when index reaches end, add current path to results.
if (isdigit(s[i]))Digits do not branch; append digit and recurse to next index.
path.push_back(tolower(s[i]));Try lowercase branch for current letter to explore one variation.
path.pop_back();Backtrack by removing last character to restore state.
path.push_back(toupper(s[i]));Try uppercase branch for current letter to explore the other variation.
function letterCasePermutation(s) {
    const res = [];
    function backtrack(i, path) {
        if (i === s.length) {
            res.push(path);
            return;
        }
        const c = s[i];
        if (/[0-9]/.test(c)) {
            backtrack(i + 1, path + c);
        } else {
            backtrack(i + 1, path + c.toLowerCase());
            backtrack(i + 1, path + c.toUpperCase());
        }
    }
    backtrack(0, "");
    return res;
}

// Driver code
console.log(letterCasePermutation("a1b2"));
Line Notes
function letterCasePermutation(s)Main function to generate all permutations from input string.
function backtrack(i, path)Recursive helper tracking current index and the path string built so far.
if (i === s.length)Base case: when index reaches end, add current path to results.
if (/[0-9]/.test(c))Digits do not branch; recurse with same character appended.
backtrack(i + 1, path + c.toLowerCase())Try lowercase branch for current letter to explore one variation.
backtrack(i + 1, path + c.toUpperCase())Try uppercase branch for current letter to explore the other variation.
Complexity
TimeO(2^k * n) where k is number of letters and n is string length
SpaceO(n) recursion stack + O(2^k * n) output space

Each letter doubles the number of permutations, digits do not branch. We build strings of length n for each permutation.

💡 For example, if input has 3 letters, we get 2^3=8 permutations, each of length n, so about 8*n operations.
Interview Verdict: Accepted

This brute force approach is accepted for typical constraints and is the foundation for more optimized solutions.

🧠
Iterative BFS / Queue Approach
💡 This approach uses a queue to iteratively build permutations level by level, which can be easier to understand for those uncomfortable with recursion.

Intuition

Start with an empty string in a queue. For each character, if digit, append it to all strings in queue. If letter, for each string, append lowercase and uppercase versions, doubling queue size.

Algorithm

  1. Initialize a queue with an empty string.
  2. For each character in input string:
  3. If digit, append it to all strings in queue.
  4. If letter, for each string in queue, create two new strings with lowercase and uppercase appended.
  5. After processing all characters, queue contains all permutations.
💡 The tricky part is managing the queue size doubling when letters appear and ensuring all strings are updated correctly.
</>
Code
from collections import deque
from typing import List

def letterCasePermutation(s: str) -> List[str]:
    queue = deque([''])
    for c in s:
        n = len(queue)
        if c.isdigit():
            for _ in range(n):
                queue.append(queue.popleft() + c)
        else:
            for _ in range(n):
                curr = queue.popleft()
                queue.append(curr + c.lower())
                queue.append(curr + c.upper())
    return list(queue)

# Driver code
if __name__ == '__main__':
    print(letterCasePermutation("a1b2"))
Line Notes
queue = deque([''])Initialize queue with empty string as starting point for building permutations.
for c in s:Process each character in input string sequentially to build permutations stepwise.
if c.isdigit():Digits do not branch; append digit to each string in queue.
for _ in range(n):Process current queue size to avoid infinite loop while expanding queue.
queue.append(curr + c.lower())Append lowercase version for letter to build one branch.
queue.append(curr + c.upper())Append uppercase version for letter to build the other branch.
import java.util.*;

public class LetterCasePermutation {
    public static List<String> letterCasePermutation(String s) {
        LinkedList<String> queue = new LinkedList<>();
        queue.add("");
        for (char c : s.toCharArray()) {
            int n = queue.size();
            if (Character.isDigit(c)) {
                for (int i = 0; i < n; i++) {
                    queue.add(queue.poll() + c);
                }
            } else {
                for (int i = 0; i < n; i++) {
                    String curr = queue.poll();
                    queue.add(curr + Character.toLowerCase(c));
                    queue.add(curr + Character.toUpperCase(c));
                }
            }
        }
        return queue;
    }

    public static void main(String[] args) {
        System.out.println(letterCasePermutation("a1b2"));
    }
}
Line Notes
LinkedList<String> queue = new LinkedList<>();Initialize queue with empty string to start building permutations.
for (char c : s.toCharArray())Iterate over each character in input string to process sequentially.
if (Character.isDigit(c))Digits do not branch; append digit to each string in queue.
for (int i = 0; i < n; i++)Process current queue size to avoid infinite loop while expanding queue.
queue.add(curr + Character.toLowerCase(c));Add lowercase version for letter to build one branch.
queue.add(curr + Character.toUpperCase(c));Add uppercase version for letter to build the other branch.
#include <iostream>
#include <vector>
#include <string>
#include <queue>
using namespace std;

class Solution {
public:
    vector<string> letterCasePermutation(string s) {
        queue<string> q;
        q.push("");
        for (char c : s) {
            int n = q.size();
            if (isdigit(c)) {
                for (int i = 0; i < n; i++) {
                    string curr = q.front(); q.pop();
                    q.push(curr + c);
                }
            } else {
                for (int i = 0; i < n; i++) {
                    string curr = q.front(); q.pop();
                    q.push(curr + (char)tolower(c));
                    q.push(curr + (char)toupper(c));
                }
            }
        }
        vector<string> res;
        while (!q.empty()) {
            res.push_back(q.front());
            q.pop();
        }
        return res;
    }
};

int main() {
    Solution sol;
    vector<string> res = sol.letterCasePermutation("a1b2");
    for (auto& str : res) cout << str << endl;
    return 0;
}
Line Notes
queue<string> q;Initialize queue with empty string to start building permutations.
for (char c : s)Iterate over each character in input string sequentially.
if (isdigit(c))Digits do not branch; append digit to each string in queue.
for (int i = 0; i < n; i++)Process current queue size to avoid infinite loop while expanding queue.
q.push(curr + (char)tolower(c));Add lowercase version for letter to build one branch.
q.push(curr + (char)toupper(c));Add uppercase version for letter to build the other branch.
function letterCasePermutation(s) {
    let queue = [''];
    for (const c of s) {
        const n = queue.length;
        if (/[0-9]/.test(c)) {
            for (let i = 0; i < n; i++) {
                queue[i] = queue[i] + c;
            }
        } else {
            const temp = [];
            for (let i = 0; i < n; i++) {
                temp.push(queue[i] + c.toLowerCase());
                temp.push(queue[i] + c.toUpperCase());
            }
            queue = temp;
        }
    }
    return queue;
}

// Driver code
console.log(letterCasePermutation("a1b2"));
Line Notes
let queue = [''];Initialize queue with empty string to start building permutations.
for (const c of s)Iterate over each character in input string sequentially.
if (/[0-9]/.test(c))Digits do not branch; append digit to each string in queue by replacing strings.
for (let i = 0; i < n; i++)Process all strings in queue to append current character.
temp.push(queue[i] + c.toLowerCase());Add lowercase version for letter to build one branch.
temp.push(queue[i] + c.toUpperCase());Add uppercase version for letter to build the other branch.
queue = temp;Replace queue with expanded list after processing letter to maintain correct permutations.
Complexity
TimeO(2^k * n) where k is number of letters and n is string length
SpaceO(2^k * n) for queue and output

Each letter doubles the queue size, digits do not branch. We build strings of length n for each permutation.

💡 This iterative approach uses a queue to build permutations stepwise, which can be easier to visualize than recursion.
Interview Verdict: Accepted

This approach is accepted and useful when recursion is not preferred or stack depth is a concern.

🧠
Backtracking with In-Place Character Array Modification
💡 This approach optimizes memory by modifying the input character array in place during recursion, reducing string concatenation overhead.

Intuition

Instead of building new strings at each recursion, we toggle the case of letters in the character array and recurse, then revert changes to backtrack.

Algorithm

  1. Convert input string to character array.
  2. At each index, if digit, recurse to next index.
  3. If letter, recurse twice: once with lowercase, once with uppercase by modifying array in place.
  4. When index reaches end, convert array to string and add to results.
  5. Backtrack by reverting character case changes.
💡 The key is to remember to revert changes after recursive calls to maintain correct state.
</>
Code
from typing import List

def letterCasePermutation(s: str) -> List[str]:
    res = []
    arr = list(s)
    def backtrack(i: int):
        if i == len(arr):
            res.append(''.join(arr))
            return
        if arr[i].isdigit():
            backtrack(i + 1)
        else:
            arr[i] = arr[i].lower()
            backtrack(i + 1)
            arr[i] = arr[i].upper()
            backtrack(i + 1)
            arr[i] = s[i]  # revert to original
    backtrack(0)
    return res

# Driver code
if __name__ == '__main__':
    print(letterCasePermutation("a1b2"))
Line Notes
arr = list(s)Convert string to list for in-place modification to avoid costly string concatenations.
def backtrack(i: int):Recursive helper function with current index to explore permutations.
if i == len(arr):Base case: when index reaches end, join array and add to results.
if arr[i].isdigit():Digits do not branch; recurse to next index directly.
arr[i] = arr[i].lower()Set current letter to lowercase to explore one branch.
arr[i] = arr[i].upper()Set current letter to uppercase to explore the other branch.
arr[i] = s[i] # revert to originalBacktrack by restoring original character to maintain correct state.
import java.util.*;

public class LetterCasePermutation {
    public static List<String> letterCasePermutation(String s) {
        List<String> res = new ArrayList<>();
        char[] arr = s.toCharArray();
        backtrack(arr, 0, res, s);
        return res;
    }

    private static void backtrack(char[] arr, int i, List<String> res, String original) {
        if (i == arr.length) {
            res.add(new String(arr));
            return;
        }
        if (Character.isDigit(arr[i])) {
            backtrack(arr, i + 1, res, original);
        } else {
            arr[i] = Character.toLowerCase(arr[i]);
            backtrack(arr, i + 1, res, original);
            arr[i] = Character.toUpperCase(arr[i]);
            backtrack(arr, i + 1, res, original);
            arr[i] = original.charAt(i); // revert
        }
    }

    public static void main(String[] args) {
        System.out.println(letterCasePermutation("a1b2"));
    }
}
Line Notes
char[] arr = s.toCharArray();Convert string to char array for efficient in-place modifications.
private static void backtrack(char[] arr, int i, List<String> res, String original)Recursive helper with index and original string to revert changes.
if (i == arr.length)Base case: when index reaches end, add current permutation to results.
if (Character.isDigit(arr[i]))Digits do not branch; recurse to next index directly.
arr[i] = Character.toLowerCase(arr[i]);Set current letter to lowercase to explore one branch.
arr[i] = Character.toUpperCase(arr[i]);Set current letter to uppercase to explore the other branch.
arr[i] = original.charAt(i); // revertBacktrack by restoring original character to maintain correct state.
#include <iostream>
#include <vector>
#include <string>
using namespace std;

class Solution {
public:
    vector<string> letterCasePermutation(string s) {
        vector<string> res;
        backtrack(s, 0, res, s);
        return res;
    }

private:
    void backtrack(string& arr, int i, vector<string>& res, const string& original) {
        if (i == arr.size()) {
            res.push_back(arr);
            return;
        }
        if (isdigit(arr[i])) {
            backtrack(arr, i + 1, res, original);
        } else {
            arr[i] = tolower(arr[i]);
            backtrack(arr, i + 1, res, original);
            arr[i] = toupper(arr[i]);
            backtrack(arr, i + 1, res, original);
            arr[i] = original[i]; // revert
        }
    }
};

int main() {
    Solution sol;
    vector<string> res = sol.letterCasePermutation("a1b2");
    for (auto& str : res) cout << str << endl;
    return 0;
}
Line Notes
void backtrack(string& arr, int i, vector<string>& res, const string& original)Recursive helper with reference to string for in-place edits and original for revert.
if (i == arr.size())Base case: when index reaches end, add current permutation to results.
if (isdigit(arr[i]))Digits do not branch; recurse to next index directly.
arr[i] = tolower(arr[i]);Set current letter to lowercase to explore one branch.
arr[i] = toupper(arr[i]);Set current letter to uppercase to explore the other branch.
arr[i] = original[i]; // revertBacktrack by restoring original character to maintain correct state.
function letterCasePermutation(s) {
    const res = [];
    const arr = s.split('');
    function backtrack(i) {
        if (i === arr.length) {
            res.push(arr.join(''));
            return;
        }
        if (/[0-9]/.test(arr[i])) {
            backtrack(i + 1);
        } else {
            arr[i] = arr[i].toLowerCase();
            backtrack(i + 1);
            arr[i] = arr[i].toUpperCase();
            backtrack(i + 1);
            arr[i] = s[i]; // revert
        }
    }
    backtrack(0);
    return res;
}

// Driver code
console.log(letterCasePermutation("a1b2"));
Line Notes
const arr = s.split('');Convert string to array for efficient in-place modification.
function backtrack(i)Recursive helper with current index to explore permutations.
if (i === arr.length)Base case: when index reaches end, join array and add to results.
if (/[0-9]/.test(arr[i]))Digits do not branch; recurse to next index directly.
arr[i] = arr[i].toLowerCase();Set current letter to lowercase to explore one branch.
arr[i] = arr[i].toUpperCase();Set current letter to uppercase to explore the other branch.
arr[i] = s[i]; // revertBacktrack by restoring original character to maintain correct state.
Complexity
TimeO(2^k * n) where k is number of letters and n is string length
SpaceO(n) recursion stack + O(2^k * n) output space

We modify the input array in place, avoiding string concatenation overhead, but still explore all permutations.

💡 This approach is more memory efficient than building new strings each recursion, which can matter for large inputs.
Interview Verdict: Accepted

This is a practical optimization of the brute force approach, often preferred in interviews for cleaner code and better performance.

📊
All Approaches - One-Glance Tradeoffs
💡 For most interviews, the in-place backtracking approach is best to code due to clarity and efficiency.
ApproachTimeSpaceStack RiskReconstructUse In Interview
1. Brute Force RecursionO(2^k * n)O(n) recursion stack + O(2^k * n) outputYes (deep recursion for large k)YesMention and code if comfortable with recursion
2. Iterative BFS / QueueO(2^k * n)O(2^k * n) for queue and outputNoYesGood alternative if recursion is risky
3. In-Place BacktrackingO(2^k * n)O(n) recursion stack + O(2^k * n) outputYesYesPreferred approach to code for clarity and efficiency
💼
Interview Strategy
💡 Use this guide to understand the problem deeply before interviews. Start by clarifying the problem, then explain brute force, and finally optimize. Practice coding and testing thoroughly.

How to Present

Step 1: Clarify input constraints and output format.Step 2: Describe brute force recursive backtracking approach.Step 3: Discuss iterative BFS approach as alternative.Step 4: Present in-place backtracking optimization.Step 5: Code chosen approach and test with examples.

Time Allocation

Clarify: 2min → Approach: 5min → Code: 10min → Test: 3min. Total ~20min

What the Interviewer Tests

Interviewer tests your understanding of recursion/backtracking, handling branching logic, edge cases, and optimization skills.

Common Follow-ups

  • What if input is very large? → Discuss pruning or iterative approach.
  • Can you do this without recursion? → Use iterative BFS with queue.
  • How to handle Unicode or special characters? → Clarify problem constraints.
  • What is the maximum output size? → 2^k where k is number of letters.
💡 These follow-ups test your ability to adapt solutions, optimize, and clarify assumptions.
🔍
Pattern Recognition

When to Use

1) Problem asks for all subsets or permutations with variations; 2) Input contains letters and digits; 3) Need to toggle letter cases; 4) Output all possible strings.

Signature Phrases

toggle caseall possible stringsletter or digit

NOT This Pattern When

Problems that require counting permutations without generating them or greedy selection problems

Similar Problems

Permutations - generates all orderingsSubsets - generates all subsets of a setCombination Sum - explores combinations with backtracking

Practice

(1/5)
1. You need to find all unique combinations of exactly k distinct numbers from 1 to 9 that add up to a target sum n. Which algorithmic approach guarantees finding all valid combinations efficiently by exploring partial solutions and pruning impossible paths early?
easy
A. Greedy algorithm that picks the largest numbers first until the sum is reached or exceeded
B. Backtracking with pruning based on current sum and remaining numbers' possible sums
C. Dynamic programming that counts combinations without generating them explicitly
D. Sorting the numbers and using two pointers to find pairs that sum to n

Solution

  1. Step 1: Understand problem constraints

    The problem requires all unique combinations of size k from numbers 1 to 9 summing to n, which suggests exploring subsets.
  2. Step 2: Identify suitable algorithm

    Backtracking with pruning efficiently explores partial combinations and stops early when sums cannot reach n, guaranteeing correctness and efficiency.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Backtracking with pruning is standard for combination sum problems [OK]
Hint: Backtracking with pruning finds all valid combos efficiently [OK]
Common Mistakes:
  • Thinking greedy or two pointers can find all combinations
  • Confusing counting with generating combinations
2. You are given an array of positive integers and a number k. The task is to determine if the array can be partitioned into k subsets such that the sum of elements in each subset is equal. Which algorithmic approach guarantees an optimal solution for this problem?
easy
A. Dynamic programming based on subset sums without pruning or memoization
B. Greedy algorithm that picks the largest elements first and assigns them to subsets
C. Backtracking with bitmask memoization to explore subsets and prune invalid states
D. Sorting and then using a sliding window to find equal sum partitions

Solution

  1. Step 1: Understand problem constraints and complexity

    The problem requires partitioning into exactly k subsets with equal sums, which is NP-complete and requires exploring combinations exhaustively.
  2. Step 2: Evaluate algorithm suitability

    Greedy and sliding window approaches fail to guarantee correctness because they don't explore all combinations. Simple DP without pruning is inefficient and incomplete. Backtracking with bitmask memoization efficiently prunes and caches states, guaranteeing optimality.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Backtracking with memoization handles all subsets optimally [OK]
Hint: Bitmask memoization prunes repeated subset states [OK]
Common Mistakes:
  • Assuming greedy always works for equal sum partition
  • Confusing subset sum DP with partitioning into k subsets
3. The following code attempts to solve Combination Sum III but contains a subtle bug. Identify the line causing incorrect results or inefficiency.
medium
A. Line appending comb directly to res without copying
B. Line calculating min_sum for pruning
C. Line popping last element from comb after recursion
D. Line checking if total > n to prune early

Solution

  1. Step 1: Identify how results are stored

    Appending comb directly stores a reference, so later modifications affect stored results.
  2. Step 2: Understand impact

    Must append a copy (comb[:]) to avoid all results being the same final list state.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Appending reference causes all results to be identical after backtracking [OK]
Hint: Always append a copy of combination, not the list reference [OK]
Common Mistakes:
  • Appending reference instead of copy
  • Missing pruning conditions
4. The following code attempts to solve Combination Sum (Reuse Allowed). Identify the line containing the subtle bug that causes incorrect results or inefficiency:
def combinationSum(candidates, target):
    candidates.sort()
    result = []
    def backtrack(index, path, target):
        if target == 0:
            result.append(path[:])
            return
        if index == len(candidates) or target < 0:
            return
        max_use = target // candidates[index]
        for count in range(max_use + 1):
            path += [candidates[index]] * count
            backtrack(index + 1, path, target - candidates[index] * count)
            # Missing path restoration here
    backtrack(0, [], target)
    return result
medium
A. Line with 'path += [candidates[index]] * count' because path is modified without backtracking (pop).
B. Line with 'candidates.sort()' because sorting is unnecessary.
C. Line with 'if target == 0:' because it should check for target <= 0.
D. Line with 'max_use = target // candidates[index]' because integer division may cause errors.

Solution

  1. Step 1: Analyze path modification in loop

    Path is extended by count copies of candidates[index] but never restored after recursive call, causing path to grow incorrectly across iterations.
  2. Step 2: Identify missing backtracking step

    Proper backtracking requires removing added elements after recursion to restore path state for next iteration.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Modifying path without restoration leads to incorrect combinations [OK]
Hint: Always restore path after recursion in backtracking [OK]
Common Mistakes:
  • Forgetting to pop elements after recursion
  • Assuming path copy avoids mutation issues
5. Identify the bug in the following code snippet for counting max bitwise-OR subsets:
from typing import List

class Solution:
    def countMaxOrSubsets(self, nums: List[int]) -> int:
        n = len(nums)
        max_or = 0
        count = 0
        for mask in range(0, 1 << n):  # Note: starts from 0
            current_or = 0
            for i in range(n):
                if mask & (1 << i):
                    current_or |= nums[i]
            if current_or > max_or:
                max_or = current_or
                count = 1
            elif current_or == max_or:
                count += 1
        return count
medium
A. The count variable should be reset inside the inner loop
B. The OR operation should be replaced with AND
C. The loop should start from 1 to exclude empty subset
D. max_or should be initialized to -1 instead of 0

Solution

  1. Step 1: Identify that mask=0 represents empty subset

    Empty subset OR is 0, which is usually not counted as a valid subset.
  2. Step 2: Recognize that including empty subset inflates count incorrectly

    Starting from mask=0 causes counting empty subset, leading to wrong final count.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Exclude empty subset by starting mask from 1 -> correct counting [OK]
Hint: Empty subset mask=0 must be excluded to avoid incorrect counts [OK]
Common Mistakes:
  • Counting empty subset as valid
  • Incorrect initialization of max_or