Given a string num
representing a positive integer and an integer k
, you are asked to find the minimum number of adjacent swaps required to transform num
into its k
-th smallest permutation (in lexicographical order). Each swap can only exchange two adjacent digits.
k
-th smallest permutation that is strictly larger than the current num
.i
and i+1
).
At first glance, the problem seems to require generating all permutations of the string until reaching the k
-th one, then counting swaps. However, generating all permutations is highly inefficient, especially for long numbers.
Instead, we can observe that:
k
-th next permutation (not all permutations).k
-th next lexicographical permutation of num
.Let's break down the solution into clear steps:
k
-th Next Permutation:
k
times.This approach works because moving a digit leftward to its correct position using adjacent swaps is always optimal and doesn't affect the order of earlier digits.
Let's walk through an example to see how the process works:
Input: num = "5489355142"
, k = 4
["5489355412", "5489355421", "5489359124", "5489359142"]
."5489359142"
.3
.k
times is O(k * n), where n is the length of num
.
The problem is elegantly solved by decomposing it into two manageable subproblems: efficiently finding the k
-th next permutation using the standard algorithm, and then counting the minimum adjacent swaps needed to reach this permutation from the original string. By focusing on adjacent swaps and leveraging the properties of permutations, we avoid brute-force methods and achieve an efficient, practical solution. This approach demonstrates the power of breaking complex problems into logical steps and applying well-known algorithms in creative ways.
class Solution:
def getMinSwaps(self, num: str, k: int) -> int:
def next_permutation(arr):
n = len(arr)
i = n - 2
while i >= 0 and arr[i] >= arr[i + 1]:
i -= 1
if i == -1:
return False
j = n - 1
while arr[j] <= arr[i]:
j -= 1
arr[i], arr[j] = arr[j], arr[i]
arr[i + 1:] = reversed(arr[i + 1:])
return True
original = list(num)
target = list(num)
for _ in range(k):
next_permutation(target)
swaps = 0
temp = original[:]
for i in range(len(temp)):
if temp[i] != target[i]:
j = i + 1
while temp[j] != target[i]:
j += 1
while j > i:
temp[j], temp[j - 1] = temp[j - 1], temp[j]
swaps += 1
j -= 1
return swaps
class Solution {
public:
int getMinSwaps(string num, int k) {
string target = num;
for (int i = 0; i < k; ++i) {
next_permutation(target.begin(), target.end());
}
int swaps = 0;
string temp = num;
int n = temp.size();
for (int i = 0; i < n; ++i) {
if (temp[i] != target[i]) {
int j = i + 1;
while (temp[j] != target[i]) ++j;
while (j > i) {
swap(temp[j], temp[j - 1]);
swaps++;
j--;
}
}
}
return swaps;
}
};
class Solution {
public int getMinSwaps(String num, int k) {
char[] target = num.toCharArray();
for (int i = 0; i < k; ++i) {
nextPermutation(target);
}
char[] temp = num.toCharArray();
int swaps = 0;
int n = temp.length;
for (int i = 0; i < n; ++i) {
if (temp[i] != target[i]) {
int j = i + 1;
while (temp[j] != target[i]) j++;
while (j > i) {
char t = temp[j];
temp[j] = temp[j - 1];
temp[j - 1] = t;
swaps++;
j--;
}
}
}
return swaps;
}
private void nextPermutation(char[] arr) {
int n = arr.length, i = n - 2;
while (i >= 0 && arr[i] >= arr[i + 1]) i--;
if (i >= 0) {
int j = n - 1;
while (arr[j] <= arr[i]) j--;
char t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
reverse(arr, i + 1, n - 1);
}
private void reverse(char[] arr, int l, int r) {
while (l < r) {
char t = arr[l];
arr[l++] = arr[r];
arr[r--] = t;
}
}
}
var getMinSwaps = function(num, k) {
function nextPermutation(arr) {
let n = arr.length, i = n - 2;
while (i >= 0 && arr[i] >= arr[i + 1]) i--;
if (i >= 0) {
let j = n - 1;
while (arr[j] <= arr[i]) j--;
[arr[i], arr[j]] = [arr[j], arr[i]];
}
let l = i + 1, r = n - 1;
while (l < r) {
[arr[l], arr[r]] = [arr[r], arr[l]];
l++; r--;
}
}
let original = num.split('');
let target = num.split('');
for (let i = 0; i < k; ++i) {
nextPermutation(target);
}
let swaps = 0;
let temp = original.slice();
for (let i = 0; i < temp.length; ++i) {
if (temp[i] !== target[i]) {
let j = i + 1;
while (temp[j] !== target[i]) j++;
while (j > i) {
[temp[j], temp[j - 1]] = [temp[j - 1], temp[j]];
swaps++;
j--;
}
}
}
return swaps;
};