LeetCode #402 Medium

Remove K Digits

Remove exactly k digits from a numeric string so the remaining number is the smallest possible.

monotonic-stackgreedystrings
Open on LeetCode ↗
02

Intuition

💡

The stack part of this problem is the easy half; nearly every wrong submission passes the pop logic and fails on the cleanup after. If the sweep never finds anything worth popping — the string is already non-decreasing, like "12345" — k removals still remain unspent, and they have to come off the end, where place value is lowest, not the front. Then the result can start with zeros the stack never stripped, and if k equals the string length the whole stack empties and returning an empty string is wrong. Sweep left to right with a stack, popping while the top exceeds the incoming digit and removals remain, and treat the cleanups as mandatory, not optional.

03

Approach

1

Find the highest-value removal

If digit d is immediately followed by a smaller digit, removing d promotes something smaller into a more significant position, which always lowers the number. Any digit followed by a larger one is better kept, since removing it would promote something bigger.

2

Enforce it with a monotonic stack

Push digits left to right. While the stack top is greater than the incoming digit and k > 0, pop and decrement k. Each pop is exactly the removal identified above, applied as early — and therefore as significantly — as possible.

3

Handle the leftovers

Three cleanups, and skipping any one fails a real test case. If k remains after the sweep, the string is non-decreasing, so remove from the end with st[:-k] — removing from the front is the mistake, since the front already passed through the pop logic. Strip leading zeros with lstrip('0'). If nothing survives, return "0" rather than an empty string. O(n) time, O(n) space.

04

Solution & live demo

python
1class Solution:
2 def removeKdigits(self, num, k):
3 st = []
4 for ch in num:
5 while k and st and st[-1] > ch:
6 st.pop()
7 k -= 1
8 st.append(ch)
9 if k:
10 st = st[:-k]
11 res = ''.join(st).lstrip('0')
12 return res or '0'
05

Edge cases

k equals the length of the string

Everything is removed, so return "0".

Leading zeros after removal, e.g. "10200" with k=1

Strip them — the answer is "200", not "0200".

Already non-decreasing, e.g. "12345"

No pops fire, so the trailing removal path handles all of k.

Result is entirely zeros

Stripping empties the string, so the explicit "0" fallback is required.

06

Complexity

Time
O(n)
Space
O(n)
Each digit is pushed and popped at most once; the cleanups are linear.