1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Solution {
public String removeKdigits(String num, int k) {
int[] nextSmaller = new int[num.length()];
Arrays.fill(nextSmaller, -1);
char[] numArray = num.toCharArray();
Deque<Integer> monoStack = new ArrayDeque<>();
for (int i = 0; i < numArray.length; i++) {
while (!monoStack.isEmpty() && numArray[i] < numArray[monoStack.peek()]) {
nextSmaller[monoStack.pop()] = i;
}
monoStack.push(i);
}
StringBuilder ans = new StringBuilder();
int ptr = 0;
while (ptr < nextSmaller.length) {
if (nextSmaller[ptr] != -1 && nextSmaller[ptr] - ptr <= k) {
k -= nextSmaller[ptr] - ptr;
ptr = nextSmaller[ptr];
} else {
if (ans.length() != 0 || numArray[ptr] != '0') {
ans.append(numArray[ptr]);
}
ptr += 1;
}
}
ans.setLength(Math.max(0, ans.length() - k));
return ans.length() == 0 ? "0" : ans.toString();
}
}

mono stack. 我们需要知道每一个digit它的next smaller是谁. 如果一个digit的next smaller距离自己的距离小于等于k, 那么我们可以把从自己到next smaller之前的数字都删掉, 同时也更新k的值. k就代表能删掉多少digits. 如果一个digit没有next smaller, 我们就暂时保留它. 等到最后, 如果k没用完, 那我们把最后的k个删掉(如果不足k个就都删掉). 这是因为留下来的都是没有next smaller的, 或者有但是距离太远的. 因此它们的位置已经是我们能够达到最小的位置了. 如果我们从前往后删除, 只会让数字更大. 因此我们从后面开始删除.

时间复杂度: O(n) 遍历两次num, n是num的长度.
空间复杂度: O(n) 用到了stack.