You are given a string num
representing the digits of a very large integer and an integer k
. You are allowed to swap any two adjacent digits of the integer at most k
times.
Return the minimum integer you can obtain also as a string.
Example 1:
Input: num = "4321", k = 4 Output: "1342" Explanation: The steps to obtain the minimum integer from 4321 with 4 adjacent swaps are shown.
Example 2:
Input: num = "100", k = 1 Output: "010" Explanation: It's ok for the output to have leading zeros, but the input is guaranteed not to have any leading zeros.
Example 3:
Input: num = "36789", k = 1000 Output: "36789" Explanation: We can keep the number without any swaps.
Constraints:
1 <= num.length <= 3 * 104
num
consists of only digits and does not contain leading zeros.1 <= k <= 109
This problem asks to find the lexicographically smallest integer that can be obtained by performing at most k adjacent swaps on the digits of the input number. The solution uses a Binary Indexed Tree (BIT) to efficiently track the cumulative swaps and a greedy approach to select the smallest available digits.
Algorithm:
Initialization:
BinaryIndexedTree
(BIT) of size n
(length of the input number) to track the number of swaps performed on each position. The BIT allows for efficient querying of the cumulative sum of swaps up to a given index and updating the sum at an index in O(log n) time.pos
) to store the indices of each digit (0-9) in the input number. This helps to quickly find the positions of the available digits.Greedy Selection:
i
(1 to n
) of the output string.v
:
pos[v]
list is not empty).dist
to swap the smallest available digit v
to the current position i
. This distance is calculated using the BIT:
tree.query(n) - tree.query(j)
: Gets the total number of swaps performed before position j
.j - i
: Accounts for the additional swaps required to move digit v
from position j
to position i
.dist <= k
: Sufficient swaps remaining.
k
by subtracting dist
.j
from pos[v]
.v
to the output string.tree.update(j, 1)
to reflect that a swap has been performed at position j
.Return Result: Return the constructed output string.
Time Complexity: O(10n log n). The outer loop iterates n
times. The inner loop iterates 10 times (for each digit). BIT operations (query and update) take O(log n) time.
Space Complexity: O(n). The BIT and the pos
list use linear space.
Code Explanation (Python):
The Python code implements the above algorithm using a BinaryIndexedTree
class. The minInteger
function performs the greedy selection and uses a defaultdict(deque)
to efficiently manage the indices of each digit. The deque is chosen for efficient removal of the first element.
Code Explanation (Java, C++, Go):
The Java, C++, and Go code provide similar implementations, with the main differences being in syntax and data structures. They all follow the same algorithmic approach using a BinaryIndexedTree
and a greedy strategy. The choice of data structure (e.g., ArrayDeque
in Java, queue<int>
in C++, and a slice in Go) for managing digit indices is tailored to the respective language.
This solution efficiently finds the minimum integer possible within the constraints of at most k adjacent swaps. The use of a Binary Indexed Tree is crucial for optimizing the computation of the total number of swaps required for each digit placement.