Maximum Value after Insertion
You are given a string n representing a large integer (possibly negative) and a single digit x (0 through 9). You need to insert x somewhere in n so that the resulting number is as large as possible. Return the result as a string.
This is LeetCode 1881: Maximum Value after Insertion, a medium problem that tests whether you can apply greedy reasoning to string manipulation. The trick is that positive and negative numbers require opposite insertion strategies.
Positive number
n = "99", x = 9. No digit is smaller than 9, so insert at the front (or anywhere). Result: "999".
Positive number
n = "73", x = 6. Digit 7 is not smaller than 6, but 3 is. Insert 6 before the 3. Result: "763".
Negative number
n = "-13", x = 2. Scanning digits: 1 is not greater than 2, but 3 is. Insert 2 before the 3. Result: "-123".
Why greedy works here
The value of a number depends most heavily on its leftmost digits. A larger digit in an earlier position contributes more to the total value. For a positive number, you want x as far left as possible, but only as long as it does not displace a digit that is already larger. So you scan left to right and insert x right before the first digit that is smaller than x. If every digit is at least as large as x, you append it at the end.
For a negative number, the logic flips. A negative number with a smaller absolute value is "larger" (closer to zero). You want the absolute value to be as small as possible, which means placing smaller digits earlier. So you scan left to right and insert x right before the first digit that is greater than x. If no digit is greater, you append x at the end.
A useful mental shortcut: for positive numbers, find the first digit where x would be an upgrade (the digit is smaller). For negative numbers, find the first digit where x would reduce the damage (the digit is larger). In both cases you are greedily placing x to improve the number as early as possible.
The code
def max_value(n: str, x: int) -> str:
x_char = str(x)
if n[0] != '-':
# Positive: insert before the first digit smaller than x
for i, ch in enumerate(n):
if ch < x_char:
return n[:i] + x_char + n[i:]
return n + x_char
else:
# Negative: insert before the first digit greater than x
for i in range(1, len(n)):
if n[i] > x_char:
return n[:i] + x_char + n[i:]
return n + x_char
The function checks the sign of n by looking at the first character. For a positive number, it scans every character from left to right. The moment it finds a digit ch that is less than x_char (using string comparison, which works because single-digit characters sort by numeric value), it inserts x right before that position. For a negative number, it starts scanning at index 1 (skipping the '-' sign) and looks for the first digit greater than x_char. If the loop finishes without finding a suitable position, x goes at the end.
String comparison works here because both ch and x_char are single characters representing digits 0 through 9. The ASCII ordering of '0' through '9' matches numeric ordering, so '3' < '7' is equivalent to 3 < 7.
Visual walkthrough
Step 1: Check the sign
x = 6The number "473" is positive. For a positive number, we want the result to be as large as possible. Scan left to right for the first digit smaller than x (6).
Step 2: Scan digit '4'
x = 6Digit '4' at index 0. Is 4 less than 6? Yes. We found our insertion point.
Step 3: Insert before '4'
x = 6Insert 6 before index 0. Result: "6473". Placing the larger digit earlier makes the positive number bigger.
Step 4: Negative example, check the sign
x = 6The number "-473" is negative. For a negative number, we want the absolute value to be as small as possible. Scan left to right for the first digit greater than x (6).
Step 5: Scan digit '4'
x = 6Digit '4' at index 1 (skipping the '-' sign). Is 4 greater than 6? No. Move on.
Step 6: Scan digit '7'
x = 6Digit '7' at index 2. Is 7 greater than 6? Yes. We found our insertion point.
Step 7: Insert before '7'
x = 6Insert 6 before index 2. Result: "-4673". Placing the smaller digit earlier keeps the negative number closer to zero.
The first three steps show the positive case: scanning "473" for the first digit less than 6. The digit 4 qualifies immediately, so 6 is inserted at the front to produce "6473". The last four steps show the negative case: scanning "-473" for the first digit greater than 6. The digit 4 does not qualify, but 7 does, so 6 is inserted before the 7 to produce "-4673".
Complexity analysis
| Metric | Value |
|---|---|
| Time | O(n) where n is the length of the number string |
| Space | O(n) for the result string |
The scan visits each character at most once, giving linear time. The result string is one character longer than the input, so it requires O(n) space. There is no way to do better, since you need to read every digit to decide the correct position and you need to construct the output string.
Building blocks
Greedy insertion point
The core pattern here is scanning a sequence to find the first position where a greedy condition holds. You walk through the elements left to right, and the moment the condition triggers, you act. If the condition never triggers, you use a default position (the end). This same pattern appears in problems like Insert Interval (find the first interval that starts after the new one) and Search Insert Position (find where a target would go in a sorted array). The skeleton is always the same:
for i, element in enumerate(sequence):
if condition(element, target):
return insert_at(i)
return insert_at_end()
Sign-aware optimization
When a problem involves both positive and negative numbers, the optimization direction often reverses. For positive values, "bigger is better" in leading positions. For negative values, "smaller is better" in leading positions, because a smaller absolute value means a larger actual value. This sign-aware reversal shows up in problems involving sorting by absolute value, greedy scheduling with profits and penalties, and any scenario where the sign of a quantity changes what "optimal" means.
The key is to identify the two cases cleanly and handle them with the same structure but opposite comparison operators.
Edge cases
Before submitting, make sure your solution handles these:
- All digits equal to x: for
n = "555"andx = 5, every digit equalsx, so no digit is smaller (positive case). Append at the end to get"5555". Any position gives the same result. - Single-digit positive:
n = "3"andx = 7. Since3 < 7, insert before index 0 to get"73". - x is 0 and n is positive:
n = "12"andx = 0. Digits 1 and 2 are both greater than 0, so append to get"120". Inserting 0 at the front would not be valid as a standalone number, but the problem guaranteesnis already a valid representation, so appending is correct. - Negative number where no digit exceeds x:
n = "-132"andx = 9. No digit in "132" is greater than 9, so append to get"-1329". The 9 goes at the end, keeping the absolute value contribution minimal. - Very long number string: the algorithm handles strings up to 10^5 characters in a single linear pass, well within time limits.
From understanding to recall
You have read the greedy solution and it makes sense. One scan, one comparison, one insertion. But can you write it from scratch in an interview without looking at it?
The details matter: checking the sign with n[0] != '-', starting the negative-case loop at index 1 (not 0), using < for positive and > for negative, and remembering to append at the end as the fallback. These are small but critical, and they are easy to mix up under pressure if you have not practiced writing them from memory.
Spaced repetition closes that gap. You practice writing the sign-check and greedy-scan loop from scratch at increasing intervals. After a few rounds, the pattern is automatic. You see "insert digit to maximize value" and the code flows out without hesitation.
The greedy insertion-point pattern is one of roughly 60 reusable building blocks that cover hundreds of LeetCode problems. Learning them individually and drilling them with spaced repetition is far more effective than grinding random problems and hoping they stick.
Related posts
- Add Strings - String-based number manipulation
- Can Convert String in k Moves - String transformation with positional decisions
- Break a Palindrome - Greedy character replacement in a string