A permutation of an array of integers is an arrangement of its members into a sequence or linear order.
arr = [1,2,3]
, the following are all the permutations of arr
: [1,2,3], [1,3,2], [2, 1, 3], [2, 3, 1], [3,1,2], [3,2,1]
.The next permutation of an array of integers is the next lexicographically greater permutation of its integer. More formally, if all the permutations of the array are sorted in one container according to their lexicographical order, then the next permutation of that array is the permutation that follows it in the sorted container. If such arrangement is not possible, the array must be rearranged as the lowest possible order (i.e., sorted in ascending order).
arr = [1,2,3]
is [1,3,2]
.arr = [2,3,1]
is [3,1,2]
.arr = [3,2,1]
is [1,2,3]
because [3,2,1]
does not have a lexicographical larger rearrangement.Given an array of integers nums
, find the next permutation of nums
. The replacement must be in place and use only constant extra memory. Give the optimal solution. Explain Big(O) run-time. Explain Big(O) space usage. Break down edge cases.
Example:
nums = [1,2,3]
should produce [1,3,2]
nums = [3,2,1]
should produce [1,2,3]
nums = [1,1,5]
should produce [1,5,1]
A simple but inefficient approach would be to generate all possible permutations of the input array, sort them lexicographically, and then find the permutation that comes after the given input array.
Algorithm:
Code (Python):
import itertools
def next_permutation_brute_force(nums):
permutations = sorted(list(itertools.permutations(nums)))
# Find the index of the current permutation
for i in range(len(permutations)):
if list(nums) == list(permutations[i]):
current_index = i
break
else:
return sorted(nums) # Handle the case where nums is not in permutations (shouldn't happen normally)
# Return the next permutation, or the first if it's the last
if current_index == len(permutations) - 1:
return list(permutations[0])
else:
return list(permutations[current_index + 1])
Time Complexity: O(n! * n log(n))
Space Complexity: O(n! * n)
A more efficient, in-place algorithm can find the next permutation without generating all possible permutations.
Algorithm:
nums[i]
that is smaller than its next element nums[i+1]
. If no such element is found, the array is in descending order, and we need to reverse the entire array to get the smallest permutation.nums[j]
that is greater than nums[i]
.nums[i]
and nums[j]
.nums[i+1]
to the end of the array. This ensures that the suffix is in ascending order, resulting in the next lexicographical permutation.Edge Cases:
Code (Python):
def next_permutation(nums):
n = len(nums)
# 1. Find the first decreasing element
i = n - 2
while i >= 0 and nums[i] >= nums[i + 1]:
i -= 1
if i >= 0:
# 2. Find the smallest element to swap
j = n - 1
while j >= 0 and nums[j] <= nums[i]:
j -= 1
# 3. Swap
nums[i], nums[j] = nums[j], nums[i]
# 4. Reverse the suffix
left = i + 1
right = n - 1
while left < right> nums[right]:
left, right = right, left
return nums
Time Complexity: O(n)
Space Complexity: O(1)