# 1505. Minimum Possible Integer After at Most K Adjacent Swaps On Digits

## Description

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

## Solutions

Segment Tree.

• class Solution {
public String minInteger(String num, int k) {
Queue<Integer>[] pos = new Queue[10];
for (int i = 0; i < 10; ++i) {
pos[i] = new ArrayDeque<>();
}
int n = num.length();
for (int i = 0; i < n; ++i) {
pos[num.charAt(i) - '0'].offer(i + 1);
}
StringBuilder ans = new StringBuilder();
BinaryIndexedTree tree = new BinaryIndexedTree(n);
for (int i = 1; i <= n; ++i) {
for (int v = 0; v < 10; ++v) {
if (!pos[v].isEmpty()) {
Queue<Integer> q = pos[v];
int j = q.peek();
int dist = tree.query(n) - tree.query(j) + j - i;
if (dist <= k) {
k -= dist;
q.poll();
ans.append(v);
tree.update(j, 1);
break;
}
}
}
}
return ans.toString();
}
}

class BinaryIndexedTree {
private int n;
private int[] c;

public BinaryIndexedTree(int n) {
this.n = n;
c = new int[n + 1];
}

public void update(int x, int delta) {
while (x <= n) {
c[x] += delta;
x += lowbit(x);
}
}

public int query(int x) {
int s = 0;
while (x > 0) {
s += c[x];
x -= lowbit(x);
}
return s;
}

public static int lowbit(int x) {
return x & -x;
}
}

• class BinaryIndexedTree {
public:
int n;
vector<int> c;

BinaryIndexedTree(int _n)
: n(_n)
, c(_n + 1) {}

void update(int x, int delta) {
while (x <= n) {
c[x] += delta;
x += lowbit(x);
}
}

int query(int x) {
int s = 0;
while (x > 0) {
s += c[x];
x -= lowbit(x);
}
return s;
}

int lowbit(int x) {
return x & -x;
}
};

class Solution {
public:
string minInteger(string num, int k) {
vector<queue<int>> pos(10);
int n = num.size();
for (int i = 0; i < n; ++i) pos[num[i] - '0'].push(i + 1);
BinaryIndexedTree* tree = new BinaryIndexedTree(n);
string ans = "";
for (int i = 1; i <= n; ++i) {
for (int v = 0; v < 10; ++v) {
auto& q = pos[v];
if (!q.empty()) {
int j = q.front();
int dist = tree->query(n) - tree->query(j) + j - i;
if (dist <= k) {
k -= dist;
q.pop();
ans += (v + '0');
tree->update(j, 1);
break;
}
}
}
}
return ans;
}
};

• class BinaryIndexedTree:
def __init__(self, n):
self.n = n
self.c = [0] * (n + 1)

@staticmethod
def lowbit(x):
return x & -x

def update(self, x, delta):
while x <= self.n:
self.c[x] += delta
x += BinaryIndexedTree.lowbit(x)

def query(self, x):
s = 0
while x:
s += self.c[x]
x -= BinaryIndexedTree.lowbit(x)
return s

class Solution:
def minInteger(self, num: str, k: int) -> str:
pos = defaultdict(deque)
for i, v in enumerate(num, 1):
pos[int(v)].append(i)
ans = []
n = len(num)
tree = BinaryIndexedTree(n)
for i in range(1, n + 1):
for v in range(10):
q = pos[v]
if q:
j = q[0]
dist = tree.query(n) - tree.query(j) + j - i
if dist <= k:
k -= dist
q.popleft()
ans.append(str(v))
tree.update(j, 1)
break
return ''.join(ans)


• type BinaryIndexedTree struct {
n int
c []int
}

func newBinaryIndexedTree(n int) *BinaryIndexedTree {
c := make([]int, n+1)
return &BinaryIndexedTree{n, c}
}

func (this *BinaryIndexedTree) lowbit(x int) int {
return x & -x
}

func (this *BinaryIndexedTree) update(x, delta int) {
for x <= this.n {
this.c[x] += delta
x += this.lowbit(x)
}
}

func (this *BinaryIndexedTree) query(x int) int {
s := 0
for x > 0 {
s += this.c[x]
x -= this.lowbit(x)
}
return s
}

func minInteger(num string, k int) string {
pos := make([][]int, 10)
for i, c := range num {
pos[c-'0'] = append(pos[c-'0'], i+1)
}
n := len(num)
tree := newBinaryIndexedTree(n)
var ans strings.Builder
for i := 1; i <= n; i++ {
for v := 0; v < 10; v++ {
if len(pos[v]) > 0 {
j := pos[v][0]
dist := tree.query(n) - tree.query(j) + j - i
if dist <= k {
k -= dist
pos[v] = pos[v][1:]
ans.WriteByte(byte(v + '0'))
tree.update(j, 1)
break
}
}
}
}
return ans.String()
}