Skip to content
← All posts

Maximum Value after Insertion

6 min read
leetcodeproblemmediumstringsgreedy

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

insert999

n = "99", x = 9. No digit is smaller than 9, so insert at the front (or anywhere). Result: "999".

Positive number

insert763

n = "73", x = 6. Digit 7 is not smaller than 6, but 3 is. Insert 6 before the 3. Result: "763".

Negative number

insert-123

n = "-13", x = 2. Scanning digits: 1 is not greater than 2, but 3 is. Insert 2 before the 3. Result: "-123".

Green cells show where the digit is inserted to maximize the value. For positive numbers, insert before the first smaller digit. For negative numbers, insert before the first larger digit.

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 = 6
n473

The 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 = 6
n473

Digit '4' at index 0. Is 4 less than 6? Yes. We found our insertion point.

Step 3: Insert before '4'

x = 6
result6473inserted

Insert 6 before index 0. Result: "6473". Placing the larger digit earlier makes the positive number bigger.

Step 4: Negative example, check the sign

x = 6
n-473

The 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 = 6
n-473

Digit '4' at index 1 (skipping the '-' sign). Is 4 greater than 6? No. Move on.

Step 6: Scan digit '7'

x = 6
n-473

Digit '7' at index 2. Is 7 greater than 6? Yes. We found our insertion point.

Step 7: Insert before '7'

x = 6
result-4673inserted

Insert 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

MetricValue
TimeO(n) where n is the length of the number string
SpaceO(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" and x = 5, every digit equals x, 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" and x = 7. Since 3 < 7, insert before index 0 to get "73".
  • x is 0 and n is positive: n = "12" and x = 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 guarantees n is already a valid representation, so appending is correct.
  • Negative number where no digit exceeds x: n = "-132" and x = 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