2259. Remove Digit From Number to Maximize Result
Problem Description
You are given a string number
that represents a positive integer and a character digit
.
Your task is to remove exactly one occurrence of the character digit
from the string number
. After removing this digit, the remaining characters form a new number. You need to choose which occurrence of digit
to remove such that the resulting number is as large as possible.
For example, if number = "1231"
and digit = "1"
, you have two choices:
- Remove the first
"1"
to get"231"
- Remove the second
"1"
to get"123"
Since "231"
is larger than "123"
, you would return "231"
.
The problem guarantees that the character digit
appears at least once in the string number
, so there will always be at least one valid removal option.
The solution approach iterates through each position in the string where digit
appears, creates a new string by removing that occurrence (concatenating the part before and after that position), and returns the maximum value among all possible results.
Intuition
Since we need to remove exactly one occurrence of a specific digit to maximize the resulting number, we need to think about which occurrence to remove when the digit appears multiple times.
The key insight is that when comparing numbers as strings, they are compared lexicographically (character by character from left to right). For example, "231"
> "123"
because at the first position, '2'
> '1'
.
Given that we must remove one digit, we have a finite number of choices - we can only remove from positions where our target digit appears. If the digit appears k
times, we have exactly k
different possible results.
Rather than trying to devise a clever rule about which occurrence to remove (which could get complicated considering various edge cases), we can leverage the fact that we have limited options. We can simply:
- Try removing the digit from each position where it appears
- Generate all possible resulting strings
- Compare them and pick the maximum
This brute force approach works efficiently because:
- The number of positions to check is at most the length of the string
- String comparison in Python naturally gives us the lexicographically largest string
- Using the
max()
function with a generator expression makes the code concise and readable
The beauty of this solution is its simplicity - instead of overthinking the problem with complex logic about when to remove which digit, we let Python's built-in max()
function handle the comparison for us.
Learn more about Greedy patterns.
Solution Approach
The solution uses a brute force enumeration approach combined with Python's built-in string manipulation and comparison capabilities.
Algorithm Steps:
-
Enumerate all positions: We iterate through each position
i
in the stringnumber
usingenumerate()
, which gives us both the index and the character at that position. -
Filter target digit positions: We only consider positions where the character
d
equals our targetdigit
. This is done using the conditionif d == digit
in the generator expression. -
Generate candidate strings: For each valid position
i
wherenumber[i] == digit
, we create a new string by:- Taking the prefix:
number[:i]
(all characters before positioni
) - Taking the suffix:
number[i + 1:]
(all characters after positioni
) - Concatenating them:
number[:i] + number[i + 1:]
This effectively removes the character at position
i
. - Taking the prefix:
-
Find maximum: We use Python's
max()
function to find the lexicographically largest string among all candidates. Since strings are compared character by character from left to right, this gives us the numerically largest result.
Example walkthrough:
If number = "1231"
and digit = "1"
:
- Position 0:
d = "1"
matches, generate"" + "231" = "231"
- Position 1:
d = "2"
doesn't match, skip - Position 2:
d = "3"
doesn't match, skip - Position 3:
d = "1"
matches, generate"123" + "" = "123"
- Return
max(["231", "123"]) = "231"
The time complexity is O(nΒ²)
where n
is the length of the string, as we potentially create n
new strings, each of length n-1
. The space complexity is O(nΒ²)
in the worst case if all characters are the target digit.
Ready to land your dream job?
Unlock your dream job with a 3-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through a concrete example to understand how the solution works.
Example: number = "52352"
and digit = "5"
We need to remove exactly one occurrence of "5"
to get the largest possible number.
Step 1: Identify positions where digit appears
- Position 0:
"5"
β (matches our target digit) - Position 1:
"2"
β (not our target) - Position 2:
"3"
β (not our target) - Position 3:
"5"
β (matches our target digit) - Position 4:
"2"
β (not our target)
So digit "5"
appears at positions 0 and 3.
Step 2: Generate all possible results by removing each occurrence
For position 0 (remove first "5"
):
- Prefix:
number[:0] = ""
- Suffix:
number[1:] = "2352"
- Result:
"" + "2352" = "2352"
For position 3 (remove second "5"
):
- Prefix:
number[:3] = "523"
- Suffix:
number[4:] = "2"
- Result:
"523" + "2" = "5232"
Step 3: Compare all candidates and select maximum
We have two candidates: "2352"
and "5232"
Comparing lexicographically (character by character):
- First character:
"2"
vs"5"
β"5"
is greater - Therefore
"5232" > "2352"
Final Answer: "5232"
This demonstrates why we need to check all positions - removing the first occurrence gives "2352"
, but removing the second occurrence gives us the larger result "5232"
. The algorithm correctly identifies this by trying both removals and selecting the maximum.
Solution Implementation
1class Solution:
2 def removeDigit(self, number: str, digit: str) -> str:
3 """
4 Remove one occurrence of the specified digit from the number string
5 to get the maximum possible resulting number.
6
7 Args:
8 number: A string representing a positive integer
9 digit: A single digit character to be removed
10
11 Returns:
12 The maximum number as a string after removing one occurrence of digit
13 """
14 # Generate all possible numbers by removing each occurrence of the target digit
15 # and return the maximum value among them
16 return max(
17 number[:i] + number[i + 1:] # Concatenate parts before and after index i
18 for i, current_digit in enumerate(number) # Iterate through each character with its index
19 if current_digit == digit # Only consider positions where the digit matches
20 )
21
1class Solution {
2 /**
3 * Removes one occurrence of the specified digit from the number string
4 * to create the largest possible number.
5 *
6 * @param number The input number as a string
7 * @param digit The digit character to be removed
8 * @return The largest possible number after removing one occurrence of the digit
9 */
10 public String removeDigit(String number, char digit) {
11 // Initialize result with smallest possible value
12 String maxResult = "0";
13
14 // Get the length of the input number
15 int length = number.length();
16
17 // Iterate through each character in the number
18 for (int index = 0; index < length; index++) {
19 // Get the current character at this position
20 char currentChar = number.charAt(index);
21
22 // Check if current character matches the digit to remove
23 if (currentChar == digit) {
24 // Create a new string by removing the character at current index
25 // Concatenate the part before index with the part after index
26 String candidateNumber = number.substring(0, index) + number.substring(index + 1);
27
28 // Update maxResult if the candidate number is larger
29 // compareTo returns negative if maxResult is lexicographically less than candidateNumber
30 if (maxResult.compareTo(candidateNumber) < 0) {
31 maxResult = candidateNumber;
32 }
33 }
34 }
35
36 return maxResult;
37 }
38}
39
1class Solution {
2public:
3 string removeDigit(string number, char digit) {
4 // Initialize the result with the smallest possible value
5 string maxResult = "0";
6
7 // Get the length of the input number string
8 int length = number.size();
9
10 // Iterate through each character in the number string
11 for (int i = 0; i < length; ++i) {
12 char currentChar = number[i];
13
14 // Check if the current character matches the target digit
15 if (currentChar == digit) {
16 // Create a new string by removing the current digit
17 // Concatenate the substring before index i with the substring after index i
18 string candidateNumber = number.substr(0, i) + number.substr(i + 1);
19
20 // Update the result if the new number is lexicographically larger
21 if (maxResult < candidateNumber) {
22 maxResult = candidateNumber;
23 }
24 }
25 }
26
27 // Return the maximum number after removing one occurrence of the digit
28 return maxResult;
29 }
30};
31
1/**
2 * Removes one occurrence of a specified digit from a number string to create the largest possible result
3 * @param number - The input number as a string
4 * @param digit - The digit to be removed (as a string)
5 * @returns The largest possible number string after removing one occurrence of the digit
6 */
7function removeDigit(number: string, digit: string): string {
8 const length: number = number.length;
9 let lastOccurrenceIndex: number = -1;
10
11 // Iterate through each character in the number string
12 for (let i: number = 0; i < length; ++i) {
13 // Check if current character matches the target digit
14 if (number[i] === digit) {
15 // Update the last occurrence index
16 lastOccurrenceIndex = i;
17
18 // If the next digit exists and is greater than current digit,
19 // removing current digit will create the largest possible number
20 if (i + 1 < length && number[i] < number[i + 1]) {
21 break;
22 }
23 }
24 }
25
26 // Remove the digit at the determined index and return the result
27 return number.substring(0, lastOccurrenceIndex) + number.substring(lastOccurrenceIndex + 1);
28}
29
Time and Space Complexity
Time Complexity: O(nΒ²)
The code iterates through the string number
to find all occurrences of the target digit
. For each occurrence found, it creates a new string by concatenating number[:i]
and number[i+1:]
, which takes O(n)
time for string slicing and concatenation. If there are k
occurrences of the digit (where k β€ n
), we create k
strings, each requiring O(n)
time. After generating all possible strings, the max()
function compares them, which takes O(k * n)
time since string comparison is O(n)
. Therefore, the overall time complexity is O(k * n) = O(nΒ²)
in the worst case when k
approaches n
.
Space Complexity: O(nΒ²)
The generator expression creates up to k
strings, where each string has length n-1
. In the worst case, when all characters are the target digit, we would have n
strings of length n-1
, requiring O(n * (n-1)) = O(nΒ²)
space. However, since we're using a generator expression with max()
, Python needs to store all generated strings in memory simultaneously to perform the comparison. Additionally, each string slice operation creates a new string object. Therefore, the total space complexity is O(nΒ²)
.
Note: The reference answer states space complexity as O(n)
, which would be true if only considering the space for a single string at a time. However, the max()
function needs to materialize all strings from the generator to compare them, leading to O(nΒ²)
space usage.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
Pitfall 1: Attempting Numerical Comparison Instead of String Comparison
A common mistake is trying to convert the resulting strings to integers for comparison, which can lead to overflow issues with very large numbers or unnecessary complexity.
Incorrect approach:
def removeDigit(self, number: str, digit: str) -> str:
candidates = []
for i, d in enumerate(number):
if d == digit:
candidates.append(int(number[:i] + number[i + 1:]))
return str(max(candidates))
Why it's problematic:
- Python integers can handle arbitrarily large numbers, but this adds unnecessary conversion overhead
- In other languages, this could cause integer overflow for very long number strings
- String comparison naturally gives us the lexicographically largest result, which corresponds to the numerically largest value for strings of the same length
Solution: Stick with string comparison as shown in the original solution. Python's string comparison works left-to-right, character by character, which correctly identifies the largest numerical value.
Pitfall 2: Greedy Approach - Removing First Occurrence Where Next Digit is Larger
A tempting optimization is to use a greedy approach: find the first occurrence of the target digit where the next character is larger, or remove the last occurrence if no such position exists.
Incorrect greedy approach:
def removeDigit(self, number: str, digit: str) -> str:
last_index = -1
for i in range(len(number)):
if number[i] == digit:
last_index = i
# If next digit is larger, remove current digit immediately
if i < len(number) - 1 and number[i] < number[i + 1]:
return number[:i] + number[i + 1:]
# If no increasing pattern found, remove the last occurrence
return number[:last_index] + number[last_index + 1:]
Why it works (and when to use it): This greedy approach actually produces the correct answer and is more efficient with O(n) time complexity. The logic is:
- If we find a target digit followed by a larger digit, removing it immediately maximizes the result
- If no such position exists, removing the rightmost occurrence minimizes the impact on the larger place values
When to choose each approach:
- Use the brute force approach when code simplicity and readability are priorities, or when the string length is small
- Use the greedy approach when optimizing for performance with longer strings
Both solutions are valid, but understanding the trade-off between simplicity and efficiency is crucial for interview discussions.
The three-steps of Depth First Search are:
- Identify states;
- Draw the state-space tree;
- DFS on the state-space tree.
Recommended Readings
Greedy Introduction div class responsive iframe iframe src https www youtube com embed WTslqPbj7I title YouTube video player frameborder 0 allow accelerometer autoplay clipboard write encrypted media gyroscope picture in picture web share allowfullscreen iframe div When do we use greedy Greedy algorithms tend to solve optimization problems Typically they will ask you to calculate the max min of some value Commonly you may see this phrased in the problem as max min longest shortest largest smallest etc These keywords can be identified by just scanning
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Want a Structured Path to Master System Design Too? Donβt Miss This!