🧠
Brute Force (Try All Combinations)
💡 This approach exists to understand the problem's search space and why naive solutions are impractical. It helps beginners grasp the problem's complexity before optimizing.
Intuition
Try removing every possible combination of k digits and pick the smallest resulting number. This brute force method explores all subsets of digits to remove.
Algorithm
- Generate all combinations of indices of length k to remove.
- For each combination, remove those digits from num.
- Convert the remaining digits to a number, removing leading zeros.
- Return the smallest number found.
💡 This algorithm is conceptually simple but hard to implement efficiently due to the huge number of combinations.
from itertools import combinations
def removeKdigits(num: str, k: int) -> str:
if k == 0:
return str(int(num)) # remove leading zeros
if k == len(num):
return "0"
min_num = None
indices = range(len(num))
for remove_indices in combinations(indices, k):
remove_set = set(remove_indices)
candidate = ''.join(num[i] for i in range(len(num)) if i not in remove_set)
candidate = candidate.lstrip('0') or '0'
if min_num is None or int(candidate) < int(min_num):
min_num = candidate
return min_num
# Driver code
if __name__ == '__main__':
print(removeKdigits("1432219", 3)) # Expected: 1219
print(removeKdigits("10200", 1)) # Expected: 200
print(removeKdigits("10", 2)) # Expected: 0
Line Notes
from itertools import combinationsImport combinations to generate all removal sets
if k == 0:If no digits to remove, just return number without leading zeros
if k == len(num):If removing all digits, result is zero
for remove_indices in combinations(indices, k):Try every combination of k indices to remove
candidate = ''.join(num[i] for i in range(len(num)) if i not in remove_set)Build candidate number after removals
candidate = candidate.lstrip('0') or '0'Remove leading zeros or set to '0' if empty
if min_num is None or int(candidate) < int(min_num):Update minimum number found
import java.util.*;
public class RemoveKDigitsBrute {
public static String removeKdigits(String num, int k) {
if (k == 0) return removeLeadingZeros(num);
if (k == num.length()) return "0";
List<Integer> indices = new ArrayList<>();
for (int i = 0; i < num.length(); i++) indices.add(i);
String minNum = null;
List<List<Integer>> combos = combinations(indices, k);
for (List<Integer> removeIndices : combos) {
Set<Integer> removeSet = new HashSet<>(removeIndices);
StringBuilder candidate = new StringBuilder();
for (int i = 0; i < num.length(); i++) {
if (!removeSet.contains(i)) candidate.append(num.charAt(i));
}
String candStr = removeLeadingZeros(candidate.toString());
if (minNum == null || compareNumbers(candStr, minNum) < 0) minNum = candStr;
}
return minNum;
}
private static String removeLeadingZeros(String s) {
int i = 0;
while (i < s.length() && s.charAt(i) == '0') i++;
return i == s.length() ? "0" : s.substring(i);
}
private static int compareNumbers(String a, String b) {
if (a.length() != b.length()) return a.length() - b.length();
return a.compareTo(b);
}
private static List<List<Integer>> combinations(List<Integer> arr, int k) {
List<List<Integer>> result = new ArrayList<>();
backtrack(arr, k, 0, new ArrayList<>(), result);
return result;
}
private static void backtrack(List<Integer> arr, int k, int start, List<Integer> temp, List<List<Integer>> result) {
if (temp.size() == k) {
result.add(new ArrayList<>(temp));
return;
}
for (int i = start; i < arr.size(); i++) {
temp.add(arr.get(i));
backtrack(arr, k, i + 1, temp, result);
temp.remove(temp.size() - 1);
}
}
// Driver
public static void main(String[] args) {
System.out.println(removeKdigits("1432219", 3)); // 1219
System.out.println(removeKdigits("10200", 1)); // 200
System.out.println(removeKdigits("10", 2)); // 0
}
}
Line Notes
if (k == 0) return removeLeadingZeros(num);Return original number if no removals
if (k == num.length()) return "0";If removing all digits, return zero
for (List<Integer> removeIndices : combos)Try all combinations of indices to remove
StringBuilder candidate = new StringBuilder();Build candidate number after removals
String candStr = removeLeadingZeros(candidate.toString());Remove leading zeros from candidate
if (minNum == null || compareNumbers(candStr, minNum) < 0)Update minimum number found
private static void backtrack(...)Generate all combinations recursively
#include <iostream>
#include <string>
#include <vector>
#include <set>
#include <algorithm>
using namespace std;
void backtrack(const vector<int>& arr, int k, int start, vector<int>& temp, vector<vector<int>>& result) {
if ((int)temp.size() == k) {
result.push_back(temp);
return;
}
for (int i = start; i < (int)arr.size(); i++) {
temp.push_back(arr[i]);
backtrack(arr, k, i + 1, temp, result);
temp.pop_back();
}
}
vector<vector<int>> combinations(const vector<int>& arr, int k) {
vector<vector<int>> result;
vector<int> temp;
backtrack(arr, k, 0, temp, result);
return result;
}
string removeLeadingZeros(const string& s) {
int i = 0;
while (i < (int)s.size() && s[i] == '0') i++;
if (i == (int)s.size()) return "0";
return s.substr(i);
}
int compareNumbers(const string& a, const string& b) {
if ((int)a.size() != (int)b.size()) return (int)a.size() - (int)b.size();
return a.compare(b);
}
string removeKdigits(string num, int k) {
if (k == 0) return removeLeadingZeros(num);
if (k == (int)num.size()) return "0";
vector<int> indices(num.size());
for (int i = 0; i < (int)num.size(); i++) indices[i] = i;
vector<vector<int>> combos = combinations(indices, k);
string minNum = "";
for (auto& removeIndices : combos) {
set<int> removeSet(removeIndices.begin(), removeIndices.end());
string candidate = "";
for (int i = 0; i < (int)num.size(); i++) {
if (removeSet.find(i) == removeSet.end()) candidate += num[i];
}
candidate = removeLeadingZeros(candidate);
if (minNum == "" || compareNumbers(candidate, minNum) < 0) minNum = candidate;
}
return minNum;
}
int main() {
cout << removeKdigits("1432219", 3) << "\n"; // 1219
cout << removeKdigits("10200", 1) << "\n"; // 200
cout << removeKdigits("10", 2) << "\n"; // 0
return 0;
}
Line Notes
if (k == 0) return removeLeadingZeros(num);Return original number if no removals
if (k == (int)num.size()) return "0";If removing all digits, return zero
vector<vector<int>> combos = combinations(indices, k);Generate all combinations of indices to remove
string candidate = "";Build candidate number after removals
candidate = removeLeadingZeros(candidate);Remove leading zeros from candidate
if (minNum == "" || compareNumbers(candidate, minNum) < 0)Update minimum number found
void backtrack(...)Recursive helper to generate combinations
function removeKdigits(num, k) {
if (k === 0) return String(Number(num));
if (k === num.length) return "0";
const indices = [...Array(num.length).keys()];
const combos = [];
function backtrack(start, temp) {
if (temp.length === k) {
combos.push([...temp]);
return;
}
for (let i = start; i < indices.length; i++) {
temp.push(indices[i]);
backtrack(i + 1, temp);
temp.pop();
}
}
backtrack(0, []);
let minNum = null;
for (const removeIndices of combos) {
const removeSet = new Set(removeIndices);
let candidate = '';
for (let i = 0; i < num.length; i++) {
if (!removeSet.has(i)) candidate += num[i];
}
candidate = candidate.replace(/^0+/, '') || '0';
if (minNum === null || BigInt(candidate) < BigInt(minNum)) minNum = candidate;
}
return minNum;
}
// Driver
console.log(removeKdigits("1432219", 3)); // 1219
console.log(removeKdigits("10200", 1)); // 200
console.log(removeKdigits("10", 2)); // 0
Line Notes
if (k === 0) return String(Number(num));Return original number if no removals
if (k === num.length) return "0";If removing all digits, return zero
function backtrack(start, temp)Generate all combinations recursively
let candidate = '';Build candidate number after removals
candidate = candidate.replace(/^0+/, '') || '0';Remove leading zeros or set to '0'
if (minNum === null || BigInt(candidate) < BigInt(minNum))Update minimum number found
TimeO(n choose k * n)
SpaceO(n choose k * n)
We generate all combinations of k indices from n digits (n choose k), and for each, build a candidate string of length up to n.
💡 For n=10 and k=3, this means thousands of combinations; for n=100, it's astronomically large and impractical.
Interview Verdict: TLE
This approach is too slow for large inputs but is useful to understand the problem's complexity and why optimization is needed.