Remove K Digits
Remove k digits from a number-string to make the smallest result — monotonic increasing stack.
3 min read
greedy monotonic-stack string
Problem#
Remove exactly k digits from num to produce the smallest possible number (as a string, no leading zeros).
Examples#
num = "1432219", k = 3→"1219"num = "10200", k = 1→"200"
Constraints#
1 <= num.length <= 10^5.
Approach#
Monotonic increasing stack. For each digit, pop the top while top > digit and we still have removals (k > 0). Push the digit. After the loop, pop remaining k from the end. Strip leading zeros.
Solution#
class Solution {public: string removeKdigits(string num, int k) { string st; for (char c : num) { while (!st.empty() && st.back() > c && k > 0) { st.pop_back(); --k; } st.push_back(c); } while (k-- > 0 && !st.empty()) st.pop_back(); int start = 0; while (start < (int)st.size() && st[start] == '0') ++start; string ans = st.substr(start); return ans.empty() ? "0" : ans; }};func removeKdigits(num string, k int) string { st := []byte{} for i := 0; i < len(num); i++ { c := num[i] for len(st) > 0 && st[len(st)-1] > c && k > 0 { st = st[:len(st)-1] k-- } st = append(st, c) } for k > 0 && len(st) > 0 { st = st[:len(st)-1] k-- } start := 0 for start < len(st) && st[start] == '0' { start++ } ans := string(st[start:]) if ans == "" { return "0" } return ans}class Solution: def removeKdigits(self, num: str, k: int) -> str: st: list[str] = [] for c in num: while st and st[-1] > c and k > 0: st.pop() k -= 1 st.append(c) while k > 0 and st: st.pop() k -= 1 start = 0 while start < len(st) and st[start] == '0': start += 1 ans = ''.join(st[start:]) return ans if ans else "0"function removeKdigits(num, k) { const st = []; for (const c of num) { while (st.length && st[st.length - 1] > c && k > 0) { st.pop(); k--; } st.push(c); } while (k > 0 && st.length) { st.pop(); k--; } let start = 0; while (start < st.length && st[start] === '0') start++; const ans = st.slice(start).join(''); return ans === '' ? '0' : ans;}class Solution { public String removeKdigits(String num, int k) { StringBuilder st = new StringBuilder(); for (int i = 0; i < num.length(); i++) { char c = num.charAt(i); while (st.length() > 0 && st.charAt(st.length() - 1) > c && k > 0) { st.deleteCharAt(st.length() - 1); k--; } st.append(c); } while (k > 0 && st.length() > 0) { st.deleteCharAt(st.length() - 1); k--; } int start = 0; while (start < st.length() && st.charAt(start) == '0') start++; String ans = st.substring(start); return ans.isEmpty() ? "0" : ans; }}function removeKdigits(num: string, k: number): string { const st: string[] = []; for (const c of num) { while (st.length && st[st.length - 1] > c && k > 0) { st.pop(); k--; } st.push(c); } while (k > 0 && st.length) { st.pop(); k--; } let start = 0; while (start < st.length && st[start] === '0') start++; const ans = st.slice(start).join(''); return ans === '' ? '0' : ans;}Editorial#
Removing a “peak” digit (a digit larger than its right neighbor) is locally best — it lowers the digit at a high-significance position. The monotonic-stack enforces “non-decreasing from left to right” within the kept digits, which is the smallest possible.
Complexity#
- Time: O(n).
- Space: O(n).
Concept revision#
Related#