Given an array of positive integers arr (not necessarily distinct), return the lexicographically largest permutation that is smaller than arr, that can be made with exactly one swap. If it cannot be done, then return the same array.
Note that a swap exchanges the positions of two numbers arr[i] and arr[j]
Example 1:
Input: arr = [3,2,1] Output: [3,1,2] Explanation: Swapping 2 and 1.
Example 2:
Input: arr = [1,1,5] Output: [1,1,5] Explanation: This is already the smallest permutation.
Example 3:
Input: arr = [1,9,4,6,7] Output: [1,7,4,6,9] Explanation: Swapping 9 and 7.
Constraints:
1 <= arr.length <= 1041 <= arr[i] <= 104When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The brute force approach to finding the previous permutation involves checking every possible swap. We try swapping every pair of numbers and see if the resulting permutation is both smaller than the original and also the closest to the original.
Here's how the algorithm would work step-by-step:
def previous_permutation_with_one_swap_brute_force(numbers):
best_permutation = list(numbers)
found_smaller = False
for first_index in range(len(numbers)):
for second_index in range(first_index + 1, len(numbers)):
#Create a copy to simulate the swap
temp_numbers = list(numbers)
temp_numbers[first_index], temp_numbers[second_index] = temp_numbers[second_index], temp_numbers[first_index]
# Check if the swapped permutation is smaller
if temp_numbers < numbers:
# If no smaller permutation has been found yet, or the current one is larger than the previous best
if not found_smaller or temp_numbers > best_permutation:
best_permutation = temp_numbers
found_smaller = True
# If a smaller permutation was found, return it, otherwise return the original list
if found_smaller:
return best_permutation
else:
return numbersTo find the previous permutation with a single swap, we look for the rightmost place where the sequence decreases. Then, we find the largest element to the right of that place that is smaller than the element at that place and swap them.
Here's how the algorithm would work step-by-step:
def previous_permutation(numbers):
list_length = len(numbers)
for i in range(list_length - 2, -1, -1):
# Find the first element smaller than its next.
if numbers[i] > numbers[i + 1]:
right_part_index = i + 1
largest_smaller_index = i + 1
# Find largest in right part but smaller than numbers[i].
while right_part_index < list_length:
if numbers[right_part_index] < numbers[i]:
largest_smaller_index = right_part_index
else:
break
right_part_index += 1
# Swap the two numbers to get previous permutation.
numbers[i], numbers[largest_smaller_index] = numbers[largest_smaller_index], numbers[i]
return numbers
# No such previous permutation exists.
return numbers| Case | How to Handle |
|---|---|
| Null or empty input array | Return the input array immediately as no swap is possible. |
| Array with only one element | Return the input array as no swap is possible with only one element. |
| Array already in strictly descending order | Return the input array as no swap can result in a lexicographically smaller permutation. |
| Array with all identical elements | Return the input array as no swap will change the permutation. |
| Array with two elements in ascending order | Swap the two elements to create the previous permutation. |
| Large array with numbers near integer limits | Ensure no integer overflow occurs during comparison, which the provided problem does not contain so should be ignored. |
| Array contains duplicate elements preventing a larger swap | Iterate from right to left, selecting the rightmost swap that gives the largest lexicographical order, handling duplicates by prioritizing the rightmost smaller element for the swap. |
| Input array is very large, close to the maximum allowed size | The solution should have O(n) time complexity, so processing large arrays should not cause excessive delays. |