Given a non-negative integer as a string num and an integer k, remove exactly k digits so the remaining number is the smallest possible. Return it as a string (with no leading zeros; return "0" if everything is removed or the result is empty).
Input: num = "1432219", k = 3 Output: 1219 Removing 4, 3, and 2 leaves the smallest number 1219.
Input: num = "10200", k = 1 Output: 200 Remove the leading 1 to get 0200, then strip the leading zero -> 200.
- 1 <= k <= num.length <= 10^5 - num consists of only digits - num has no leading zeros except '0' itself
To make a number smallest, you want its leftmost (most significant) digits as small as possible. So whenever a digit is followed by a smaller one, deleting the larger left digit shrinks the number — and you should do that greedily while you still have removals to spend. That "remove a larger digit when a smaller one arrives" rule is a monotonic increasing stack.
“Remove exactly k, or at most k?”
Exactly k — if you don't need them all mid-string, drop the rest from the end.
“How are leading zeros and an empty result handled?”
Strip leading zeros; if nothing remains, return "0".
Smallest number means keeping the earliest digits as small as possible.
So I scan left to right with an increasing stack, popping a larger digit whenever a smaller one comes and I still have removals.
Any leftover removals I take from the end, then strip leading zeros.
Worked example — num = "1432219", k = 3
1 -> [1] 4 -> [1,4] 3 -> pop 4 (k=2) -> [1,3] 2 -> pop 3 (k=1) -> [1,2] 2 -> [1,2,2] 1 -> pop 2 (k=0) -> [1,2,1] 9 -> [1,2,1,9] result "1219"
A larger digit in a more significant place inflates the number. When a smaller digit follows, popping the larger one (if you have budget) yields a smaller result.
If removals remain after the scan, the stack is non-decreasing, so its largest digits are the trailing ones — remove those.
Popping can expose leading zeros; strip them, and return "0" if the string empties out.
| Remove one at a time | Monotonic stack | |
|---|---|---|
| Idea | k passes, each deletes the first digit bigger than its successor | One pass, pop larger digits greedily |
| Time | O(n * k) | O(n) |
| Space | O(n) | O(n) |
Full code is in the Approaches selector below.
Key takeaway
Scan left to right with an increasing stack: while you have removals and the top digit exceeds the incoming one, pop it; then push. Drop any leftover removals from the end, strip leading zeros, and return "0" if empty. O(n).
stack = []
for d in num:
while k and stack and stack.top > d: pop; k -= 1
push d
if k: stack = stack[:-k]
return join(stack) stripped of leading zeros, or "0"