AlgoMaster Logo

Remove K Digits

mediumFrequencyUpdated September 21, 2026

Understanding the Problem

We have a number represented as a string, and we need to remove exactly k digits from it to make the remaining number as small as possible. The digits stay in their original relative order (we delete digits, never reorder them).

The significance of a digit depends on its position. A larger digit sitting in a more significant position (further left) contributes more to the overall value. To minimize the number, we want smaller digits to appear as early as possible.

Consider "1432219" with one digit to remove. Scanning left to right, the first place where a digit is larger than the one right after it is the 4, which is followed by 3. Removing the 4 gives "132219", which is smaller than the result of removing any other single digit. This greedy observation is the foundation for the optimal solution.

Key Constraints:

  • 1 <= k <= num.length <= 10^5 - The string can be up to 100,000 characters long, so the solution needs to run in linear or near-linear time. Anything that enumerates combinations is far too slow.
  • num consists of only digits - No negative signs and no decimal points, so character comparison maps directly to digit comparison.
  • k <= num.length - When k equals the length, every digit is removed and the answer is "0".

Approach 1: Brute Force (Try All Combinations)

Intuition

Try every possible way to remove k digits and pick the one that gives the smallest number. With n digits and k removals, this means choosing which n - k digits to keep, in their original order.

This is essentially generating all C(n, k) subsequences of length n - k, converting each to a number, and tracking the minimum.

Algorithm

  1. Generate all combinations of n - k indices from the original string.
  2. For each combination, build the subsequence string from those indices.
  3. Strip leading zeros and compare with the current minimum.
  4. Return the smallest result found.

Visualization and Code

Loading animation...

Enumerating every combination is exponential and unusable for large inputs. The greedy observation from earlier removes the need for enumeration: a single left-to-right pass can decide each removal locally.

Approach 2: Greedy with Stack (Optimal)

Intuition

To make the result as small as possible, smaller digits should sit in the more significant (leftward) positions. So as we scan left to right, whenever a digit is smaller than the one immediately before it, removing that larger preceding digit lowers the number.

A stack carries this out cleanly. We push digits one by one. Before pushing a new digit, we compare it against the top of the stack. While the top is larger than the incoming digit and removals remain, we pop the top and count it as a removal. The stack therefore holds a non-decreasing sequence of digits read left to right, which is the smallest arrangement reachable from the prefix seen so far.

Two cases remain after the main loop. If removals are still left (k > 0), the stack is already non-decreasing, so removing from the end deletes the largest trailing digits. The result also needs its leading zeros stripped.

Algorithm

  1. Initialize an empty stack (or use a StringBuilder/list as a stack).
  2. For each digit in num:
    • While the stack is not empty, the top of the stack is greater than the current digit, and k > 0: pop from the stack and decrement k.
    • Push the current digit onto the stack.
  3. If k is still greater than 0, remove the last k digits from the stack (they are the largest remaining digits).
  4. Build the result from the stack, strip leading zeros.
  5. If the result is empty, return "0".

Visualization and Code

Loading animation...