Bird
Raised Fist0
Interview PrepbacktrackingmediumAmazonMicrosoftGoogleBloomberg

Permutations

Choose your preparation mode4 modes available
▶
Steps
setup

Initialize result and counters

The algorithm starts by copying the input array [1,2,3] into the results list and initializing the counters array c with zeros for each element.

💡 This setup is crucial because the counters track how many times each element has been swapped, enabling the algorithm to generate permutations without recursion.
Line:res = [nums[:]] c = [0] * len(nums) i = 0
💡 The initial permutation is always included, and counters start at zero to track swaps per element.
📊
Permutations - Watch the Algorithm Execute, Step by Step
Watching each swap and counter update reveals how Heap's algorithm efficiently produces permutations without recursion, making the process clear and intuitive.
Step 1/20
·Active fill★Answer cell
enteringnums=[1,2,3]
Call Path (current → root)
permute([1,2,3])
Found 1: [1,2,3]
choosingnums=[1,2,3]
Call Path (current → root)
permute([1,2,3])
Tried
no swap at i=0
Remaining
reset c[0], increment i
Found 1: [1,2,3]
backtrackingnums=[1,2,3]
Call Path (current → root)
permute([1,2,3])
Tried
reset c[0], increment i
Remaining
check c[1] < 1
Found 1: [1,2,3]
choosingnums=[1,2,3]
Call Path (current → root)
permute([1,2,3])
Tried
swap at i=1
Found 1: [1,2,3]
choosingnums=[2,1,3]
Call Path (current → root)
permute([1,2,3])
Tried
swap nums[0] and nums[1]
Found 1: [1,2,3]
backtrackingnums=[2,1,3]
Call Path (current → root)
permute([1,2,3])
Tried
added [2,1,3]
Found 2: [1,2,3] [2,1,3]
backtrackingnums=[2,1,3]
Call Path (current → root)
permute([1,2,3])
Tried
increment c[1], reset i
Remaining
check c[0] < 0
Found 2: [1,2,3] [2,1,3]
choosingnums=[2,1,3]
Call Path (current → root)
permute([1,2,3])
Tried
no swap at i=0
Remaining
reset c[0], increment i
Found 2: [1,2,3] [2,1,3]
backtrackingnums=[2,1,3]
Call Path (current → root)
permute([1,2,3])
Tried
reset c[0], increment i
Remaining
check c[1] < 1
Found 2: [1,2,3] [2,1,3]
choosingnums=[2,1,3]
Call Path (current → root)
permute([1,2,3])
Tried
no swap at i=1
Remaining
reset c[1], increment i
Found 2: [1,2,3] [2,1,3]
backtrackingnums=[2,1,3]
Call Path (current → root)
permute([1,2,3])
Tried
reset c[1], increment i
Remaining
check c[2] < 2
Found 2: [1,2,3] [2,1,3]
choosingnums=[2,1,3]
Call Path (current → root)
permute([1,2,3])
Tried
swap at i=2
Found 2: [1,2,3] [2,1,3]
choosingnums=[3,1,2]
Call Path (current → root)
permute([1,2,3])
Tried
swap nums[0] and nums[2]
Found 2: [1,2,3] [2,1,3]
backtrackingnums=[3,1,2]
Call Path (current → root)
permute([1,2,3])
Tried
added [3,1,2]
Found 3: [2,1,3] [3,1,2]
backtrackingnums=[3,1,2]
Call Path (current → root)
permute([1,2,3])
Tried
increment c[2], reset i
Remaining
check c[0] < 0
Found 3: [2,1,3] [3,1,2]
choosingnums=[3,1,2]
Call Path (current → root)
permute([1,2,3])
Tried
no swap at i=0
Remaining
reset c[0], increment i
Found 3: [2,1,3] [3,1,2]
backtrackingnums=[3,1,2]
Call Path (current → root)
permute([1,2,3])
Tried
reset c[0], increment i
Remaining
check c[1] < 1
Found 3: [2,1,3] [3,1,2]
choosingnums=[3,1,2]
Call Path (current → root)
permute([1,2,3])
Tried
swap at i=1
Found 3: [2,1,3] [3,1,2]
choosingnums=[1,3,2]
Call Path (current → root)
permute([1,2,3])
Tried
swap nums[0] and nums[1]
Found 3: [2,1,3] [3,1,2]
backtrackingnums=[1,3,2]
Call Path (current → root)
permute([1,2,3])
Tried
added [1,3,2]
Found 4: [3,1,2] [1,3,2]

Key Takeaways

✓ Heap's algorithm uses counters and parity-based swaps to generate all permutations efficiently without recursion.

This insight is hard to see from code alone because the counters' role and parity-based swapping logic are subtle and intertwined.

✓ The counters array controls how many times each element is swapped, ensuring no duplicate permutations and systematic coverage.

Understanding counters' gating role clarifies why the algorithm resets and increments indices, which is not obvious from reading code.

✓ Swapping elements based on whether the current index is even or odd ensures all permutations are generated by minimal swaps.

The parity-based swap decision is a key branching point that determines the swap pattern, which is clearer when visualized step-by-step.

Practice

(1/5)
1. What is the time complexity of the optimal iterative approach using a queue to generate all letter combinations for a digit string of length n, assuming each digit maps to at most 4 letters?
medium
A. O(n * 4^n) because we process each digit and expand combinations exponentially
B. O(2^n) because each digit doubles the number of combinations
C. O(4^n * n) because there are up to 4^n combinations and each combination is built with n concatenations
D. O(n^2) because we process n digits and each combination takes n steps

Solution

  1. Step 1: Identify number of combinations

    Each digit maps to up to 4 letters, so total combinations are up to 4^n.
  2. Step 2: Analyze work per combination

    Each combination is built by concatenating letters for n digits, so each combination requires O(n) time to build.
  3. Step 3: Simplify complexity expression

    O(4^n * n) and O(n * 4^n) are equivalent; however, O(n * 4^n) because we process each digit and expand combinations exponentially is the standard notation emphasizing processing each digit and expanding combinations exponentially.
  4. Final Answer:

    Option A -> Option A
  5. Quick Check:

    Time is exponential in n with linear cost per combination [OK]
Hint: Exponential combinations times linear build cost [OK]
Common Mistakes:
  • Confusing exponential base (2 vs 4)
  • Ignoring concatenation cost per combination
2. What is the time complexity of the optimal palindrome partitioning algorithm that uses backtracking with dynamic palindrome checks by expanding around centers for palindrome verification on a string of length n?
medium
A. O(n^2) because palindrome checks are done in constant time using DP
B. O(n^3) due to checking all substrings and palindrome verification
C. O(2^n) since all partitions are generated without extra palindrome checks
D. O(n * 2^n) because each character can start a partition and palindrome checks are O(n)

Solution

  1. Step 1: Identify number of partitions

    There are up to 2^(n-1) ways to partition a string of length n.
  2. Step 2: Analyze palindrome check cost

    Using expand around center, palindrome check per substring is O(n) worst case, done during backtracking.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Combining partitions and palindrome checks yields O(n * 2^n) [OK]
Hint: Partitions grow exponentially; palindrome checks add linear factor [OK]
Common Mistakes:
  • Assuming palindrome checks are O(1) without DP
  • Confusing total partitions with time complexity
  • Ignoring recursion stack space
3. Identify the bug in the following code snippet for getPermutation:
medium
A. Line 6: k is not converted to zero-based index before calculations.
B. Line 2: factorial array initialization is incorrect.
C. Line 10: The index calculation uses integer division incorrectly.
D. Line 12: numbers.pop(idx) should be numbers.remove(idx).

Solution

  1. Step 1: Check k adjustment

    k must be decremented by 1 to convert to zero-based indexing before using factorial divisions.
  2. Step 2: Understand impact of missing k -= 1

    Without this, idx calculation is off by one, leading to incorrect permutation output.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Missing k -= 1 causes wrong indexing and wrong permutation [OK]
Hint: Always convert k to zero-based before factorial indexing [OK]
Common Mistakes:
  • Forgetting zero-based index adjustment
  • Misusing pop vs remove
  • Incorrect factorial initialization
4. What is the time complexity of the optimal backtracking with Trie approach for Word Search II, given a board of size MxN and a list of words with maximum length L? Assume the Trie is already built.
medium
A. O(M * N * 4 * 3^(L-1)) due to pruning and adjacency constraints
B. O(M * N * 4^L * W), where W is the number of words
C. O(M * N * L^2) because each cell explores all prefixes
D. O(M * N * L) since each cell is visited once per character

Solution

  1. Step 1: Identify branching factor in backtracking

    From each cell, up to 4 directions are possible initially, then up to 3 directions for subsequent steps due to no revisiting.
  2. Step 2: Calculate complexity with pruning

    Trie pruning reduces unnecessary paths, so complexity is roughly O(M * N * 4 * 3^(L-1)) where L is max word length.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Matches known complexity from Trie + backtracking analysis [OK]
Hint: Branching factor reduces after first step due to visited constraints [OK]
Common Mistakes:
  • Confusing W (number of words) as multiplicative factor in optimal approach.
5. 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
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