Next Permutation

Problem Overview
In this article, we will delve into the "Next Permutation" problem on LeetCode, a classic problem in the realm of arrays and permutations. The problem prompts us to rearrange numbers into the lexicographically next greater permutation of numbers. If such an arrangement is not possible, it must rearrange it as the lowest possible order (sorted in ascending order). This challenge tests your understanding of permutations, arrays, and algorithms, while honing problem-solving skills crucial for technical interviews.
Understanding the Problem
To comprehend the problem, consider the following score: given a sequence, or permutation, of numbers, generate the next permutation lexicographically. For instance, the sequence [1, 2, 3]
has permutations such as [1, 3, 2]
, [2, 1, 3]
, etc. The task is to derive each subsequent permutation, and if you reach the last permutation, start with the first permutation.
Example:
Input:
[1, 2, 3]
Output:
[1, 3, 2]
Input:
[3, 2, 1]
Output:
[1, 2, 3]
Key DSA Concepts and Theory
Permutations
Permutations refer to all possible arrangements of a set of numbers. For example, given numbers [1, 2, 3]
, the permutations are 123
, 132
, 213
, 231
, 312
, 321
. Our task is to find the next arrangement after a given one — the next permutation in lexicographic order.
Lexicographic Order
This defines the arrangement similar to dictionary order applied to sequences of elements. For numbers in increasing order, the lexicographically next sequence is sought.
Algorithm Theory
This problem can be effectively solved using a single-pass algorithm. The trick lies in understanding how to manipulate the array slightly to get the next larger permutation without generating all possibilities.
Solution Approach
To find the next permutation, we need to perform the following steps:
Identify the Longest Non-Increasing Suffix:
- Traverse the array from end to start and find the first pair where
nums[i] < nums[i + 1]
. This transition marks the end of the current permutation prefix.
- Traverse the array from end to start and find the first pair where
Find Successor to the Pivot:
- If such an index was found, find the smallest element in the suffix that is larger than
nums[i]
, swap it withnums[i]
.
- If such an index was found, find the smallest element in the suffix that is larger than
Reverse the Suffix:
- Finally, reverse the order of elements from the
i+1
position onward to get the smallest lexicographic order of the suffix again.
- Finally, reverse the order of elements from the
C++ Code Example
#include <algorithm>
#include <vector>
void nextPermutation(std::vector<int>& nums) {
int i = nums.size() - 2;
// Step 1: Find the first decreasing element from the end
while (i >= 0 && nums[i] >= nums[i + 1]) {
i--;
}
// Step 2: If the entire array is non-increasing from the end, reverse it
if (i >= 0) {
int j = nums.size() - 1;
while (nums[j] <= nums[i]) {
j--;
}
// Swap the found elements
std::swap(nums[i], nums[j]);
}
// Step 3: Reverse the suffix
std::reverse(nums.begin() + i + 1, nums.end());
}
Java Code Example
import java.util.Arrays;
public class NextPermutation {
public void nextPermutation(int[] nums) {
int i = nums.length - 2;
// Step 1: Find the first decreasing element from the end
while (i >= 0 && nums[i] >= nums[i + 1]) {
i--;
}
// Step 2: If such an element exists, swap it with the smallest element on the right larger than it
if (i >= 0) {
int j = nums.length - 1;
while (nums[j] <= nums[i]) {
j--;
}
// Swap the elements
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
// Step 3: Reverse the portion of the array from i+1 onward
int start = i + 1;
int end = nums.length - 1;
while (start < end) {
int temp = nums[start];
nums[start] = nums[end];
nums[end] = temp;
start++;
end--;
}
}
}
Time and Space Complexity Analysis
Time Complexity: The algorithm runs in O(n) time because each step involves at most two linear traversals of the array — one to find the pivot, and another to swap or reverse the sequence.
Space Complexity: O(1). The transformation is done in-place, requiring no additional space.
Common Mistakes to Avoid
Handling the Entire Non-Increasing Sequence:
- Ensure proper identification of the longest non-increasing suffix. Forgetting to handle this can result in incorrect results.
In-Place Reversing After Swap:
- Many mistakes arise from incorrect reversing of the suffix after swapping the pivot element, which is crucial for maintaining lexicographic order.
Similar Problems on LeetCode
For further practice with permutations and array manipulations, consider these related problems:
- Permutations: LeetCode 46
- Permutations II: LeetCode 47
- Kth Permutation Sequence: LeetCode 60
Additional Resources and References
- Permutations in Mathematics: Wikipedia on Permutations
- Detailed Video Explanation: Search for "next permutation algorithm" on platforms like YouTube.
- Other References: Look for competitive programming tutorials that deep dive into permutations and combinatory algorithms.