Previous Permutation With One Swap
MediumUpdated: Oct 13, 2025
Practice on:
Problem
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]
Examples
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 <= 10^41 <= arr[i] <= 10^4
Solution
Method 1 - Greedy (Right-to-left Decrease & Swap)
Intuition
To get the previous permutation with one swap, we want the largest permutation smaller than the current one. We scan from right to left to find the first index i where arr[i] > arr[i+1]. Then, we swap arr[i] with the largest value to its right that is less than arr[i] (and as rightmost as possible for duplicates).
Approach
- Traverse from right to left, find the first
iwherearr[i] > arr[i+1]. - If not found, return
arr(already smallest). - From the end, find the largest
j > isuch thatarr[j] < arr[i]andarr[j] != arr[j-1](to avoid duplicate swaps). - Swap
arr[i]andarr[j]. - Return
arr.
Complexity
- ⏰ Time complexity:
O(n) - 🧺 Space complexity:
O(1)
Code
C++
#include <vector>
using namespace std;
vector<int> prevPermOpt1(vector<int>& arr) {
int n = arr.size();
for (int i = n-2; i >= 0; --i) {
if (arr[i] > arr[i+1]) {
int j = n-1;
while (arr[j] >= arr[i] || (j > 0 && arr[j] == arr[j-1])) --j;
swap(arr[i], arr[j]);
break;
}
}
return arr;
}
Code
Go
func prevPermOpt1(arr []int) []int {
n := len(arr)
for i := n-2; i >= 0; i-- {
if arr[i] > arr[i+1] {
j := n-1
for j > 0 && (arr[j] >= arr[i] || arr[j] == arr[j-1]) {
j--
}
arr[i], arr[j] = arr[j], arr[i]
break
}
}
return arr
}
Java
class Solution {
public int[] prevPermOpt1(int[] arr) {
int n = arr.length;
for (int i = n-2; i >= 0; --i) {
if (arr[i] > arr[i+1]) {
int j = n-1;
while (arr[j] >= arr[i] || (j > 0 && arr[j] == arr[j-1])) --j;
int tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp;
break;
}
}
return arr;
}
}
Kotlin
fun prevPermOpt1(arr: IntArray): IntArray {
val n = arr.size
for (i in n-2 downTo 0) {
if (arr[i] > arr[i+1]) {
var j = n-1
while (j > 0 && (arr[j] >= arr[i] || arr[j] == arr[j-1])) j--
val tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp
break
}
}
return arr
}
Python
from typing import List
def prevPermOpt1(arr: List[int]) -> List[int]:
n = len(arr)
for i in range(n-2, -1, -1):
if arr[i] > arr[i+1]:
j = n-1
while arr[j] >= arr[i] or (j > 0 and arr[j] == arr[j-1]):
j -= 1
arr[i], arr[j] = arr[j], arr[i]
break
return arr
Rust
fn prev_perm_opt1(arr: &mut Vec<i32>) -> Vec<i32> {
let n = arr.len();
for i in (0..n-1).rev() {
if arr[i] > arr[i+1] {
let mut j = n-1;
while arr[j] >= arr[i] || (j > 0 && arr[j] == arr[j-1]) {
j -= 1;
}
arr.swap(i, j);
break;
}
}
arr.clone()
}
TypeScript
export function prevPermOpt1(arr: number[]): number[] {
const n = arr.length;
for (let i = n-2; i >= 0; --i) {
if (arr[i] > arr[i+1]) {
let j = n-1;
while (arr[j] >= arr[i] || (j > 0 && arr[j] === arr[j-1])) --j;
[arr[i], arr[j]] = [arr[j], arr[i]];
break;
}
}
return arr;
}