Files
codetutor/backend/data/questions/plus-one.yaml

176 lines
7.9 KiB
YAML

title: Plus One
slug: plus-one
difficulty: easy
leetcode_id: 66
leetcode_url: https://leetcode.com/problems/plus-one/
categories:
- arrays
- math
patterns:
- slug: greedy
is_optimal: true
function_signature: "def plus_one(digits: list[int]) -> list[int]:"
test_cases:
visible:
- input: { digits: [1, 2, 3] }
expected: [1, 2, 4]
- input: { digits: [4, 3, 2, 1] }
expected: [4, 3, 2, 2]
- input: { digits: [9] }
expected: [1, 0]
hidden:
- input: { digits: [0] }
expected: [1]
- input: { digits: [9, 9] }
expected: [1, 0, 0]
- input: { digits: [1, 9] }
expected: [2, 0]
- input: { digits: [9, 9, 9] }
expected: [1, 0, 0, 0]
description: |
You are given a **large integer** represented as an integer array `digits`, where each `digits[i]` is the i<sup>th</sup> digit of the integer. The digits are ordered from most significant to least significant in left-to-right order. The large integer does not contain any leading `0`'s.
Increment the large integer by one and return *the resulting array of digits*.
constraints: |
- `1 <= digits.length <= 100`
- `0 <= digits[i] <= 9`
- `digits` does not contain any leading `0`'s
examples:
- input: "digits = [1,2,3]"
output: "[1,2,4]"
explanation: "The array represents the integer 123. Incrementing by one gives 123 + 1 = 124. Thus, the result should be [1,2,4]."
- input: "digits = [4,3,2,1]"
output: "[4,3,2,2]"
explanation: "The array represents the integer 4321. Incrementing by one gives 4321 + 1 = 4322. Thus, the result should be [4,3,2,2]."
- input: "digits = [9]"
output: "[1,0]"
explanation: "The array represents the integer 9. Incrementing by one gives 9 + 1 = 10. Thus, the result should be [1,0]."
explanation:
intuition: |
Think about how you add 1 to a number by hand. You start from the **rightmost digit** (the ones place) and add 1. If that digit is less than 9, you simply increment it and you're done. But if the digit is 9, it becomes 0 and you "carry" the 1 to the next digit on the left.
The key insight is that **carry propagation only continues while we encounter 9s**. As soon as we hit a digit that isn't 9, we can increment it, and there's no more carry to propagate. This means most numbers only require changing the last digit.
The tricky edge case is when *all* digits are 9 (like `999`). In this case, the carry propagates all the way through, and we need an extra digit at the front. The number `999 + 1 = 1000` goes from 3 digits to 4 digits.
approach: |
We solve this by **simulating the addition process** from right to left:
**Step 1: Iterate from the rightmost digit**
- Start at index `n - 1` (the last digit) and move left
- This mirrors how we do addition by hand, starting from the ones place
&nbsp;
**Step 2: Handle each digit**
- If the current digit is less than `9`, simply increment it and return the array immediately
- If the current digit is `9`, set it to `0` and continue to the next digit (the carry propagates)
&nbsp;
**Step 3: Handle the all-nines case**
- If we exit the loop without returning, every digit was `9` and is now `0`
- We need to prepend a `1` to the front
- A clean way: create a new array of length `n + 1`, set the first element to `1` (the rest default to `0`)
&nbsp;
This approach is efficient because we stop as soon as we can (no carry to propagate) and only create a new array when absolutely necessary.
common_pitfalls:
- title: Converting to Integer
description: |
A tempting approach is to convert the array to an integer, add 1, and convert back:
```python
num = int(''.join(map(str, digits)))
return [int(d) for d in str(num + 1)]
```
This works for small numbers but **fails for very large inputs**. With `digits.length <= 100`, the number could have 100 digits. This exceeds the range of standard 64-bit integers (about 19 digits). While Python handles arbitrary precision integers, this approach is inefficient and misses the point of the problem.
wrong_approach: "Convert to integer, add 1, convert back"
correct_approach: "Process digit by digit with carry propagation"
- title: Forgetting the Carry Propagation
description: |
Simply incrementing the last digit without checking for 9:
```python
digits[-1] += 1
return digits
```
This breaks for inputs like `[1, 9]` which should become `[2, 0]`, not `[1, 10]`. Every `9` must become `0` with a carry to the next position.
wrong_approach: "Only increment the last digit"
correct_approach: "Check if digit is 9 and propagate carry"
- title: Forgetting the All-Nines Case
description: |
If you don't handle the case where all digits are `9`, inputs like `[9, 9, 9]` will incorrectly return `[0, 0, 0]` instead of `[1, 0, 0, 0]`.
The array needs to grow by one element when the carry propagates past the most significant digit.
wrong_approach: "Not handling array expansion"
correct_approach: "Create a new array with leading 1 when all digits were 9"
key_takeaways:
- "**Right-to-left processing**: When simulating arithmetic operations on digit arrays, process from the least significant digit (rightmost) to handle carries naturally"
- "**Early termination**: Stop as soon as there's no carry to propagate; most cases complete after touching just one digit"
- "**Edge case awareness**: The all-nines case (`999 -> 1000`) requires special handling since the array length changes"
- "**In-place when possible**: Modify the input array directly rather than creating new arrays, except when the size must change"
time_complexity: "O(n) in the worst case, where `n` is the number of digits. We may need to visit every digit if they're all `9`s. In practice, most cases are O(1) since we return as soon as we find a non-9 digit."
space_complexity: "O(1) for most cases since we modify the array in-place. O(n) only when all digits are `9` and we need to create a new array of size `n + 1`."
solutions:
- approach_name: Right-to-Left Carry Propagation
is_optimal: true
code: |
def plus_one(digits: list[int]) -> list[int]:
n = len(digits)
# Process from rightmost digit to leftmost
for i in range(n - 1, -1, -1):
# If digit is less than 9, no carry needed
if digits[i] < 9:
digits[i] += 1
return digits
# Digit is 9, set to 0 and continue (carry propagates)
digits[i] = 0
# If we're here, all digits were 9 (e.g., 999 -> 1000)
# Create new array with leading 1
return [1] + digits
explanation: |
**Time Complexity:** O(n) — We traverse at most all n digits when all are 9s.
**Space Complexity:** O(1) for typical cases, O(n) when creating a new array for the all-nines case.
We iterate from right to left, incrementing if possible or setting to 0 and continuing. The loop naturally terminates early when we find a digit less than 9. The `[1] + digits` at the end handles the edge case where we need an extra digit.
- approach_name: Convert to Integer
is_optimal: false
code: |
def plus_one(digits: list[int]) -> list[int]:
# Join digits into a string, convert to int
num = int(''.join(map(str, digits)))
# Add one
num += 1
# Convert back to list of digits
return [int(d) for d in str(num)]
explanation: |
**Time Complexity:** O(n) — String operations on n digits.
**Space Complexity:** O(n) — Creating string representations.
This approach works in Python due to arbitrary precision integers, but it's inefficient and doesn't demonstrate understanding of the problem. It would fail in languages with fixed integer sizes for large inputs (100+ digits exceed 64-bit integers). Included to show what to avoid.