2259. Remove Digit From Number to Maximize Result
Problem Description
In this problem, you have a string number
which represents a positive integer, and a character digit
which is guaranteed to appear at least once in number
. Your task is to remove exactly one occurrence of digit
from number
, such that the new string still represents a positive integer and is as large as possible. The challenge lies in determining which occurrence of the digit
to remove in order to maximize the resulting integer.
Intuition
To arrive at the solution for this problem, it is beneficial to understand that the value of a digit in a number is dependent on its position. Specifically, the closer a digit is to the start of the number, the greater its impact on the number's overall value. Therefore, to maximize the result, we should prefer to remove a digit that is earlier in the string if it would lead to a larger subsequent digit being moved one position to the left.
The presented code iterates through the number
string and checks each occurrence of digit
. The core idea is to find the first instance of digit
which is followed by a larger digit. When this pattern is found, removing the digit
would result in increasing the overall number by having the larger digit take a more significant place. If this situation is not encountered, the code defaults to removing the last occurrence of digit
, because removing a digit closer to the end of the number has the least impact on the number's value.
Thus, by scanning left to right and leveraging the significance of digit positions, we can decide on the optimal digit to remove to maximize the integer's value.
Learn more about Greedy patterns.
Solution Approach
The implementation of the solution uses a simple for-loop to iterate over each character in the string number
. The primary data structure used here is the string itself, as we are only interested in reading its characters without the need for additional data structures.
Here is the step-by-step approach of the algorithm:
- Initialize a variable
last
with-1
, which will keep track of the index of thedigit
to be removed. - Determine the length of
number
and store it in the variablen
. - Loop through each character
d
innumber
using its indexi
. For each character: a. Check ifd
equalsdigit
. If it does: b. Updatelast
with the current indexi
. c. If this is not the last character in the string, and if the currentdigit
is less than the character following it, break the loop. - After exiting the loop, return the resulting string by concatenating the substring of
number
before the indexlast
and the substring ofnumber
after indexlast
. We skiplast
itself to "remove" the digit.
This approach leverages pattern recognition – specifically, that removing a lower digit before a higher digit will maximize the resulting number. Furthermore, it falls back on the greedy algorithm principle where local choices are made (removing the first digit
before a larger digit) in hopes of finding a global optimum – the largest possible number after removal.
This methodology guarantees that the most significant (and the first removable) digit
that leads to an increase in value is removed. The simplicity and efficiency of iterating once through the string make this solution optimal for the given task.
Ready to land your dream job?
Unlock your dream job with a 2-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's use a small example to illustrate the solution approach.
Suppose the number
given is "2736" and the digit
we need to remove is '3'. Following the solution approach described:
-
We initialize
last
with-1
. This variable will eventually hold the index of the '3' we choose to remove. -
We determine that the length of
number
(n
) is 4. -
We loop through each character
d
in "2736" using its indexi
:- At index
i
= 0,d
is '2'. It is not equal to '3', so we continue. - At index
i
= 1,d
is '7'. Again, it is not '3', so we move on. - At index
i
= 2,d
is '3'. This matches ourdigit
. We updatelast
to 2. Now, we look ahead to the next character. - The character following '3' is '6', which is greater than '3'. This means removing '3' from this position will maximize our result, as '6' will take a more significant place. We break the loop.
- At index
-
Exiting the loop, we now know the index at
last
(2 in this case) is where we want to remove ourdigit
. We return the resulting string by concatenating the substring before indexlast
("27") with the substring after indexlast
("6"), effectively skipping the '3'. The result is "276".
By this approach, we have successfully removed one instance of '3' from the number
"2736" to get the largest possible new number, which is "276". The algorithm smartly picked the '3' that preceded a larger number, thus ensuring the maximization of the resulting integer.
Solution Implementation
1class Solution:
2 def removeDigit(self, number: str, digit_to_remove: str) -> str:
3 # Initialize variable to keep track of the position where
4 # the last occurrence of the digit to remove is found
5 last_occurrence_index = -1
6 # Calculate the length of the input number string
7 number_length = len(number)
8 # Loop through each character in the number string by index and value
9 for index, digit in enumerate(number):
10 # If the current digit is the one we want to remove, update the last occurrence index
11 if digit == digit_to_remove:
12 last_occurrence_index = index
13 # Check if there's a next digit and if it's greater than the current digit,
14 # in which case, we break out of the loop to remove this particular occurrence
15 if index + 1 < number_length and digit < number[index + 1]:
16 break
17 # Return the number string with the digit removed at the last occurrence index
18 # This concatenation skips the digit to remove
19 return number[:last_occurrence_index] + number[last_occurrence_index + 1:]
20
1class Solution {
2 public String removeDigit(String number, char digit) {
3 int lastIndexOccurrence = -1; // Initialize the last index of the digit to be removed
4 int stringLength = number.length(); // Get the length of the number string
5
6 // Iterate through each character of the string
7 for (int i = 0; i < stringLength; ++i) {
8 char currentDigit = number.charAt(i); // Get the character at the current index
9
10 // Check if the current character matches the digit we want to remove
11 if (currentDigit == digit) {
12 lastIndexOccurrence = i; // Update the last index occurrence of the digit
13
14 // If the digit to remove is smaller than the next digit,
15 // and there is a next digit, break the loop
16 if (i + 1 < stringLength && currentDigit < number.charAt(i + 1)) {
17 break;
18 }
19 }
20 }
21
22 // Remove the digit at the last index occurrence and return the new string
23 return number.substring(0, lastIndexOccurrence) + number.substring(lastIndexOccurrence + 1);
24 }
25}
26
1class Solution {
2public:
3 /**
4 * Remove a single occurrence of the digit in the string such that the result is the largest possible number.
5 *
6 * @param number The string representation of the number.
7 * @param digit The digit to remove.
8 * @return The result string after the digit is removed.
9 */
10 string removeDigit(string number, char digit) {
11 int numSize = number.size(); // Get the size of the number string.
12 int lastOccurrence = -1; // Track the last occurrence index of the digit.
13
14 // Iterate through the string.
15 for (int i = 0; i < numSize; ++i) {
16 char currentDigit = number[i]; // Store the current digit.
17
18 // Check if the current digit matches the digit we want to remove.
19 if (currentDigit == digit) {
20 lastOccurrence = i; // Update the last occurrence index.
21
22 // Check if removing the current digit makes the number larger
23 // by comparing it with the next digit.
24 if (i + 1 < numSize && number[i] < number[i + 1]) {
25 // If the next digit is larger, break the loop as we've found the optimal digit to remove.
26 break;
27 }
28 }
29 }
30
31 // Remove the digit from the number using the last occurrence found.
32 // Form a new string without the digit at the last occurrence index.
33 return number.substr(0, lastOccurrence) + number.substr(lastOccurrence + 1);
34 }
35};
36
1/**
2 * Removes the first occurrence of a given digit that is followed by a larger digit,
3 * or removes the last occurrence of the digit if no such condition is met.
4 *
5 * @param {string} number - The original number represented as a string.
6 * @param {string} digit - The digit to be removed from the number.
7 * @returns {string} - The modified number as a string after removing the specified digit.
8 */
9function removeDigit(number: string, digit: string): string {
10 // Determine the length of the number string.
11 const numberLength: number = number.length;
12
13 // Initialize an index to store the position of the digit to be removed.
14 let lastOccurrenceIndex: number = -1;
15
16 // Iterate through each character in the number string.
17 for (let i = 0; i < numberLength; ++i) {
18 // Check if the current character is the digit we want to remove.
19 if (number[i] === digit) {
20 // Update the last occurrence index of the digit to the current index.
21 lastOccurrenceIndex = i;
22
23 // Check if the current digit is followed by a larger digit.
24 if (i + 1 < numberLength && number[i] < number[i + 1]) {
25 // If so, break the loop as we've found the optimal digit to remove.
26 break;
27 }
28 }
29 }
30
31 // Combine the parts of the string before and after the digit to be removed,
32 // effectively removing the digit from the number.
33 return number.substring(0, lastOccurrenceIndex) + number.substring(lastOccurrenceIndex + 1);
34}
35
Time and Space Complexity
The time complexity of the given code is O(n)
, where n
is the length of the string number
. This is because the code involves a single for-loop over the string number
, where each iteration performs a constant amount of work.
The space complexity of the given code is O(n)
. This is due to the string slicing operation number[:last] + number[last + 1 :]
, which creates a new string that can be of length up to n
. Even though Python strings are immutable and slicing creates a new string, it is essential to note that slicing may leverage copy-on-write under the hood, where the actual complexity can depend on the Python implementation. However, for complexity analysis, it is safe to state that in the worst case the space complexity is linear with respect to the length of the input string.
Learn more about how to find time and space complexity quickly using problem constraints.
How does merge sort divide the problem into subproblems?
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
LeetCode 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 we
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 algomonster s3 us east 2 amazonaws com recursion jpg You first
Want a Structured Path to Master System Design Too? Don’t Miss This!