You are given a string num
representing a large integer, and an integer k
. Your task is to make the integer as small as possible by performing at most k
adjacent swaps on the digits of num
. In each move, you can swap any two adjacent digits (i.e., swap positions i
and i+1
).
k
swaps in total, but not more.k
swaps.
At first glance, the problem seems to invite a brute-force approach: try all possible swaps and pick the smallest result. However, since the number can be very large and k
can also be large, this would be computationally infeasible.
We need to minimize the number by moving the smallest digits as far left as possible, but we are limited by the number of adjacent swaps (k
). The key insight is to always try to bring the smallest digit within the next k
positions to the current position, using as few swaps as possible.
Instead of swapping blindly, we should look ahead up to k
positions and select the smallest digit we can afford to move to the front. Then, we repeat this process for the next position, updating k
as we use swaps.
We can solve this problem using a greedy approach, iterating through each position in the string and always selecting the smallest digit within reach (i.e., within the next k
positions). Here's how:
i
in num
:
i
to i + k
(or end of string).i
(equal to the distance between its position and i
).k
, perform the swaps (i.e., move the digit to position i
, shifting the others right), and decrease k
accordingly.k
adjacent swaps.
This approach is efficient because at each step, we make the locally optimal choice that leads to a globally optimal (smallest) number, given the swap constraints.
Let's consider num = "4321"
and k = 4
.
k=4
is enough to reach all).
k = 4 - 3 = 1
.k=1
).
k = 0
.
Thus, the smallest possible integer is "1342"
.
Brute-force approach:
k
swaps, leading to exponential time complexity: O(n!/(n-k)!)k
positions to find the minimum digit. In the worst case, this is O(n*k).In practice, this is fast enough for typical constraints in coding interviews and Leetcode.
The key to this problem is recognizing that, with limited adjacent swaps, you should always bring the smallest possible digit within reach as far left as you can, using up swaps judiciously. The greedy approach ensures optimality by always making the best local choice, and the implementation is straightforward once you understand the pattern. This strategy avoids the explosion of possibilities in brute-force methods and provides an elegant, efficient solution.
class Solution:
def minInteger(self, num: str, k: int) -> str:
num = list(num)
n = len(num)
i = 0
while k > 0 and i < n:
# Find the smallest digit in the window [i, min(i+k, n-1)]
pos = i
for j in range(i+1, min(i+k+1, n)):
if num[j] < num[pos]:
pos = j
# Number of swaps needed
swaps = pos - i
if swaps > k:
break
# Bring the smallest digit to position i
for j in range(pos, i, -1):
num[j], num[j-1] = num[j-1], num[j]
k -= swaps
i += 1
return ''.join(num)
class Solution {
public:
string minInteger(string num, int k) {
int n = num.size();
int i = 0;
while (k > 0 && i < n) {
int pos = i;
for (int j = i + 1; j < n && j - i <= k; ++j) {
if (num[j] < num[pos]) {
pos = j;
}
}
int swaps = pos - i;
if (swaps > k) break;
for (int j = pos; j > i; --j) {
swap(num[j], num[j - 1]);
}
k -= swaps;
++i;
}
return num;
}
};
class Solution {
public String minInteger(String num, int k) {
char[] arr = num.toCharArray();
int n = arr.length;
int i = 0;
while (k > 0 && i < n) {
int pos = i;
for (int j = i + 1; j < n && j - i <= k; j++) {
if (arr[j] < arr[pos]) {
pos = j;
}
}
int swaps = pos - i;
if (swaps > k) break;
for (int j = pos; j > i; j--) {
char temp = arr[j];
arr[j] = arr[j - 1];
arr[j - 1] = temp;
}
k -= swaps;
i++;
}
return new String(arr);
}
}
var minInteger = function(num, k) {
let arr = num.split('');
let n = arr.length;
let i = 0;
while (k > 0 && i < n) {
let pos = i;
for (let j = i + 1; j < n && j - i <= k; j++) {
if (arr[j] < arr[pos]) {
pos = j;
}
}
let swaps = pos - i;
if (swaps > k) break;
for (let j = pos; j > i; j--) {
[arr[j], arr[j - 1]] = [arr[j - 1], arr[j]];
}
k -= swaps;
i++;
}
return arr.join('');
};