66. Plus One
On LeetCode ->Reformulated question¶
Given a non-empty list of decimal digits representing an integer, return the digits after adding one.
Example:
Key trick¶
Walk from right to left and stop as soon as a digit is not 9.
- If the current digit is
< 9, increment it and return. - If it is
9, set it to0and keep carrying. - If all digits were
9, prepend1.
Trap¶
Common mistakes:
- Converting to
intand back. - Works in Python, but misses the intended carry logic.
- Forgetting the all-
9case. - Example:
[9, 9] -> [1, 0, 0]. - Rebuilding the whole result when an in-place update is enough.
- Mutating input unexpectedly if the caller cares about reuse.
Why is this question interesting?¶
It is a tiny carry-propagation problem.
- It tests digit manipulation.
- It rewards early return.
- It is a simple example of right-to-left state propagation.
Solve the problem with idiomatic python¶
class Solution:
def plusOne(self, digits: list[int]) -> list[int]:
# Traverse from the least significant digit.
for i in range(len(digits) - 1, -1, -1):
# No carry after increment: done immediately.
if digits[i] < 9:
digits[i] += 1
return digits
# 9 + 1 becomes 0 with carry to the left.
digits[i] = 0
# If we get here, every digit was 9.
return [1] + digits
Library alternative:
- None worth using here.
int("".join(...))is less direct for this exact task.
Pytest test¶
import pytest
@pytest.mark.parametrize(
("digits", "expected"),
[
([1], [2]),
([1, 2, 3], [1, 2, 4]),
([4, 3, 2, 1], [4, 3, 2, 2]),
([1, 2, 9], [1, 3, 0]),
([1, 9, 9], [2, 0, 0]),
([9], [1, 0]),
([9, 9, 9], [1, 0, 0, 0]),
([9, 8, 7, 6, 5, 4, 3, 2, 1, 0], [9, 8, 7, 6, 5, 4, 3, 2, 1, 1]),
],
)
def test_plus_one(digits, expected):
assert Solution().plusOne(digits[:]) == expected
Comment my solution¶
Your solution is correct and handles carry well.
Good points:
- Correct carry propagation.
- Correct all-
9handling. - Clear arithmetic with
% 10and// 10.
Possible simplifications:
- You do not need a separate
outlist. - In-place right-to-left update is shorter and easier to read.
- Your test has one duplicated case:
[4,3,2,1].
import pytest
class Solution:
def plusOne(self, digits: list[int]) -> list[int]:
l = len(digits)
d = 1
out = []
for i in range(l):
out.append((digits[l - 1 - i] + d) % 10)
d = (digits[l - 1 - i] + d) // 10
if d:
out.append(d)
out.reverse()
return out
@pytest.mark.parametrize(
("digits", "expected"),
[
([1,2,3], [1,2,4]),
([4,3,2,1], [4,3,2,2]),
([4,3,2,1], [4,3,2,2]),
([9], [1,0]),
([9,9,9], [1,0,0,0]),
([1,9,9], [2,0,0]),
([9,8,7,6,5,4,3,2,1,0], [9,8,7,6,5,4,3,2,1,1])
]
)
def test_plusOne(digits, expected):
assert Solution().plusOne(digits) == expected
Extra¶
Meaning of "to carry" in algorithm description¶
In an algorithm, "to carry" refers to the same idea as in basic arithmetic: when a value exceeds the maximum allowed for a digit or position, the extra amount is passed to the next higher position.
For example, in base-10:
- If you add 1 to 9, you get 10
- You write 0 in the current position and carry 1 to the next position
So in your original sentence:
"If it is 9, set it to 0 and keep carrying"
It means:
- Reset the current digit to 0
- Then propagate a +1 to the next digit, possibly repeating the process if that digit is also 9
This is commonly used in algorithms that simulate:
- Addition
- Incrementing numbers stored as arrays
- Odometer-style counting systems
In short: "carry" = pass overflow to the next position.