Bird
Raised Fist0
Interview PrepbacktrackingmediumAmazonGoogleFacebook

Next 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 pointer i to find pivot

Set pointer i to the second last index (1) to start scanning from right to left to find the pivot where nums[i] < nums[i+1].

💡 Starting from the right helps find the first place where the sequence stops increasing, which is the pivot point for the next permutation.
Line:i = len(nums) - 2
💡 The pivot is the first element from the right that can be increased to get the next permutation.
📊
Next Permutation - Watch the Algorithm Execute, Step by Step
Watching each pointer move and swap helps you understand how the algorithm transforms the array in-place to the next permutation without generating all permutations.
Step 1/10
·Active fillAnswer cell
setup
1
0
i
2
1
3
2
compare
1
0
i
2
1
3
2
setup
1
0
i
2
1
j
3
2
compare
1
0
i
2
1
j
3
2
swap
1
0
i
3
1
j
2
2
setup
1
0
3
1
right
2
2
compare
1
0
3
1
right
2
2
move_left
1
0
3
1
right
2
2
reconstruct
1
0
3
1
2
2
Result: [1,3,2]
reconstruct
1
0
3
1
2
2
Result: [1,3,2]

Key Takeaways

The pivot is the first element from the right that breaks the descending order.

This is hard to see from code alone because the while loop hides the scanning process.

Swapping the pivot with the rightmost successor greater than it ensures the next permutation is just one step higher.

Visualizing the pointers shows why the successor must be the rightmost element greater than the pivot.

Reversing the suffix after the pivot places it in ascending order, completing the next permutation.

Without visualization, it's not obvious why reversing the suffix is necessary after swapping.

Practice

(1/5)
1. Given the following Python code for generating parentheses, what is the content of result after calling generateParenthesis(2)?
easy
A. ['((', '))']
B. ['()()', '(())']
C. ['(())', '()()']
D. ['()()', '(()']

Solution

  1. Step 1: Trace backtrack calls for n=2

    Sequences generated are '(())' and '()()' in that order due to DFS with backtracking.
  2. Step 2: Confirm order and validity

    Both sequences are valid balanced parentheses of length 4, matching expected output.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Output matches known valid sequences for n=2 [OK]
Hint: Backtracking generates sequences in DFS order [OK]
Common Mistakes:
  • Confusing order of sequences
  • Including invalid partial sequences
2. What is the time complexity of generating all permutations of an array of length n using Heap's algorithm, and why might a common misconception about this complexity be incorrect?
medium
A. O(n! * n^2) because each permutation requires n swaps and there are n! permutations
B. O(n! * log n) because Heap's algorithm uses a heap data structure internally
C. O(n! * n) because each of the n! permutations requires copying the array of length n
D. O(n! + n) because generating permutations is factorial plus linear overhead

Solution

  1. Step 1: Identify number of permutations

    There are n! permutations for an array of length n.
  2. Step 2: Analyze cost per permutation

    Heap's algorithm generates each permutation with O(1) swaps, but copying the current permutation to the result list takes O(n) time.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Time complexity is O(n! * n) due to copying each permutation [OK]
Hint: Copying each permutation costs O(n), not the swaps themselves [OK]
Common Mistakes:
  • Assuming swaps cost O(n) each or confusing heap data structure usage
3. What is the time complexity of the optimal iterative backtracking solution with pruning for restoring IP addresses from a string of length n, and why?
medium
A. O(3^4) because each of the 4 segments can be length 1 to 3, and pruning limits exploration
B. O(4^n) because each character can start a new segment or continue the previous one
C. O(n^4) because we try all partitions of the string into 4 segments
D. O(n!) due to permutations of segment lengths

Solution

  1. Step 1: Identify branching factor per segment

    Each segment can be length 1, 2, or 3, so branching factor is at most 3 per segment.
  2. Step 2: Calculate total combinations

    There are 4 segments, so total combinations are at most 3^4 = 81. Pruning further reduces this.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Time complexity depends on fixed 4 segments with max 3 choices each [OK]
Hint: Fixed 4 segments with max 3 lengths each -> 3^4 complexity [OK]
Common Mistakes:
  • Assuming complexity depends on n^4
  • Confusing permutations with combinations
4. Suppose you want to generate all valid parentheses sequences of length 2n, but now you can reuse parentheses pairs multiple times (i.e., sequences can contain repeated pairs). Which modification to the backtracking algorithm correctly handles this variant?
hard
A. Use memoization to store and reuse previously generated valid sequences to handle repeated pairs
B. Keep the original constraints but allow adding '(' or ')' even if counts exceed n, then filter duplicates after generation
C. Modify the algorithm to generate sequences of length 2n without constraints, then check validity and uniqueness
D. Remove the limit on open_count and close_count, allowing unlimited '(' and ')' additions

Solution

  1. Step 1: Understand reuse requirement

    Reusing pairs means sequences can contain repeated valid substrings; naive pruning breaks this.
  2. Step 2: Analyze modifications

    Removing limits or generating all sequences leads to invalid or duplicate sequences. Memoization allows reusing computed valid sequences efficiently.
  3. Step 3: Choose correct approach

    Memoization stores and reuses valid subsequences, enabling correct generation with reuse.
  4. Final Answer:

    Option A -> Option A
  5. Quick Check:

    Memoization handles reuse without generating invalid sequences [OK]
Hint: Memoization enables reuse without invalid sequences [OK]
Common Mistakes:
  • Removing constraints causes invalid sequences
  • Filtering duplicates after generation is inefficient
5. Suppose the problem is modified so that digits can be repeated any number of times (reuse allowed), and you want to generate all letter combinations of length n from the given digits. Which modification to the algorithm correctly handles this reuse scenario?
hard
A. Modify backtracking to allow choosing the same digit multiple times by not incrementing the index after each choice until length n is reached
B. Sort digits and generate combinations by picking letters only once per digit
C. Use dynamic programming to store combinations of length k and build up to length n without reuse
D. Use the same iterative queue approach but do not advance the digit index; instead, for each combination, append letters from all digits repeatedly until length n is reached

Solution

  1. Step 1: Understand reuse requirement

    Allowing reuse means digits can be chosen multiple times to build combinations of length n.
  2. Step 2: Identify correct approach

    Backtracking can be modified to not increment the digit index after choosing a letter, allowing reuse until length n is reached.
  3. Step 3: Why other options fail

    Iterative queue approach as-is assumes fixed digit positions; DP without reuse does not handle repeated digits; sorting and picking once per digit ignores reuse.
  4. Final Answer:

    Option A -> Option A
  5. Quick Check:

    Backtracking with flexible index handles reuse elegantly [OK]
Hint: Backtracking index controls reuse by not advancing [OK]
Common Mistakes:
  • Trying to reuse digits in iterative approach without index control
  • Ignoring reuse in DP or sorting