questions A (01-matrix - avoid-flood)

This commit is contained in:
2025-05-24 21:40:39 +01:00
parent 9fc5da3a54
commit 9eaafe4649
55 changed files with 10813 additions and 0 deletions

View File

@@ -0,0 +1,223 @@
title: Additive Number
slug: additive-number
difficulty: medium
leetcode_id: 306
leetcode_url: https://leetcode.com/problems/additive-number/
categories:
- strings
- recursion
patterns:
- backtracking
description: |
An **additive number** is a string whose digits can form an **additive sequence**.
A valid **additive sequence** should contain **at least three numbers**. Except for the first two numbers, each subsequent number in the sequence must be the sum of the preceding two.
Given a string containing only digits, return `true` if it is an **additive number** or `false` otherwise.
**Note:** Numbers in the additive sequence **cannot** have leading zeros, so sequence `1, 2, 03` or `1, 02, 3` is invalid.
constraints: |
- `1 <= num.length <= 35`
- `num` consists only of digits.
examples:
- input: 'num = "112358"'
output: "true"
explanation: "The digits can form an additive sequence: 1, 1, 2, 3, 5, 8. We have 1 + 1 = 2, 1 + 2 = 3, 2 + 3 = 5, 3 + 5 = 8."
- input: 'num = "199100199"'
output: "true"
explanation: "The additive sequence is: 1, 99, 100, 199. We have 1 + 99 = 100, 99 + 100 = 199."
- input: 'num = "1023"'
output: "false"
explanation: "No valid additive sequence can be formed. The sequence 1, 02, 3 is invalid because 02 has a leading zero."
explanation:
intuition: |
Think of this problem like solving a puzzle where you need to split a string of digits into a sequence that follows the Fibonacci-like property: each number equals the sum of the two before it.
The key insight is that **once you fix the first two numbers, the entire sequence is determined**. If we pick `num1` and `num2`, then the third number *must* be `num1 + num2`, the fourth *must* be `num2 + (num1 + num2)`, and so on. There's no choice involved after the first two numbers.
This means we can **enumerate all possible starting pairs** (the first and second numbers), then verify whether the remaining string follows the additive sequence rule. If the remaining digits perfectly match the expected sums all the way to the end, we have a valid additive number.
The constraint that numbers cannot have leading zeros (except for `"0"` itself) prunes many invalid cases early, making the search efficient despite the nested loops.
approach: |
We solve this using **Backtracking with String Enumeration**:
**Step 1: Enumerate all possible first numbers**
- The first number can be any prefix of the string from index `0` to `i`
- Skip prefixes with leading zeros (except `"0"` itself)
- The first number can be at most half the string length (we need room for at least two more numbers)
&nbsp;
**Step 2: Enumerate all possible second numbers**
- For each first number ending at index `i`, try all possible second numbers from index `i+1` to `j`
- Apply the same leading zero rule
- The combined length of the first two numbers must leave room for at least one more number
&nbsp;
**Step 3: Validate the remaining sequence**
- With `num1` and `num2` fixed, compute their sum as a string
- Check if the remaining string starts with this sum
- If yes, continue with `num2` as the new first number and the sum as the new second number
- Repeat until we consume the entire string (success) or find a mismatch (failure)
&nbsp;
**Step 4: Handle large numbers**
- Since numbers can be up to 35 digits, they may exceed integer limits
- Use string arithmetic or Python's native big integer support
&nbsp;
If any starting pair leads to consuming the entire string, return `true`. If all pairs fail, return `false`.
common_pitfalls:
- title: Missing the Leading Zero Rule
description: |
A number like `"03"` is invalid because it has a leading zero. However, `"0"` by itself is valid.
You must check: if a number has more than one digit and starts with `'0'`, skip it immediately. This applies to the first number, second number, and every computed sum in the sequence.
wrong_approach: "Allowing 01, 02, 03 as valid numbers"
correct_approach: "Skip any multi-digit number starting with '0'"
- title: Integer Overflow
description: |
With strings up to 35 digits, the numbers can far exceed the range of 64-bit integers (`2^63 - 1` has only 19 digits).
In Python, this isn't an issue due to native arbitrary-precision integers. In other languages, you'd need to implement string addition or use a big integer library.
wrong_approach: "Using int/long for arithmetic in languages with fixed-width integers"
correct_approach: "Use Python's native big integers or implement string addition"
- title: Not Trying All Starting Pairs
description: |
It's tempting to assume the first and second numbers are single digits, but consider `"199100199"` where the sequence is `1, 99, 100, 199`. The second number has two digits.
You must enumerate *all* valid lengths for both the first and second numbers.
wrong_approach: "Assuming single-digit starts or fixed-length prefixes"
correct_approach: "Try all valid prefix lengths for both first and second numbers"
- title: Forgetting the Three-Number Minimum
description: |
An additive sequence must have at least three numbers. A string like `"12"` cannot form a valid sequence even though `1 + 2 = 3` — there's no third number in the string to verify.
The validation step must consume the entire string *and* have produced at least three numbers.
wrong_approach: "Accepting two-number 'sequences'"
correct_approach: "Ensure the sequence contains at least three numbers"
key_takeaways:
- "**Constrained search space**: Fixing the first two numbers determines the entire sequence, reducing the problem to enumeration + validation"
- "**Early pruning with leading zeros**: Rejecting invalid prefixes immediately keeps the search efficient"
- "**String comparison for sums**: Instead of computing and converting, check if the string *starts with* the expected sum"
- "**Pattern recognition**: This is a classic backtracking template — enumerate choices, validate, and backtrack on failure"
time_complexity: "O(n^3). We have O(n^2) choices for the first two numbers, and validating each sequence takes O(n) time for string operations."
space_complexity: "O(n). The recursion depth is at most O(n), and we store intermediate strings of length up to O(n)."
solutions:
- approach_name: Backtracking with String Enumeration
is_optimal: true
code: |
def is_additive_number(num: str) -> bool:
n = len(num)
def is_valid(num1: str, num2: str, remaining: str) -> bool:
"""Check if remaining string follows additive sequence."""
if not remaining:
return True # Successfully consumed entire string
# Compute the expected next number
total = str(int(num1) + int(num2))
# Check if remaining starts with this sum
if not remaining.startswith(total):
return False
# Leading zero check for the sum (already handled by str(int(...)))
# Continue validation with num2 and total as the new pair
return is_valid(num2, total, remaining[len(total):])
# Try all possible first numbers (at least 1 digit, at most n-2 to leave room)
for i in range(1, n):
num1 = num[:i]
# Skip numbers with leading zeros (except "0" itself)
if len(num1) > 1 and num1[0] == '0':
break # All longer prefixes will also have leading zero
# Try all possible second numbers
for j in range(i + 1, n):
num2 = num[i:j]
# Skip numbers with leading zeros
if len(num2) > 1 and num2[0] == '0':
break # All longer second numbers starting here have leading zero
remaining = num[j:]
# Validate the sequence from this starting pair
if is_valid(num1, num2, remaining):
return True
return False
explanation: |
**Time Complexity:** O(n^3) — O(n^2) pairs of starting numbers, each validation takes O(n).
**Space Complexity:** O(n) — Recursion depth and string slicing.
We enumerate all valid (num1, num2) pairs and recursively verify that the rest of the string follows the additive property. Python's arbitrary-precision integers handle the 35-digit constraint naturally.
- approach_name: Iterative Validation
is_optimal: false
code: |
def is_additive_number(num: str) -> bool:
n = len(num)
def check_sequence(i: int, j: int) -> bool:
"""Check if starting with num[0:i] and num[i:j] forms valid sequence."""
num1 = num[:i]
num2 = num[i:j]
# Leading zero checks
if (len(num1) > 1 and num1[0] == '0') or \
(len(num2) > 1 and num2[0] == '0'):
return False
# Iterate through the rest of the string
start = j
while start < n:
# Compute expected sum
total = str(int(num1) + int(num2))
# Check if remaining string starts with sum
if not num[start:].startswith(total):
return False
# Move to next pair
start += len(total)
num1, num2 = num2, total
return True
# Enumerate all possible (i, j) pairs
# i = end of first number, j = end of second number
for i in range(1, n - 1):
for j in range(i + 1, n):
if check_sequence(i, j):
return True
return False
explanation: |
**Time Complexity:** O(n^3) — Same as recursive approach.
**Space Complexity:** O(n) — String slicing creates new strings.
This iterative version replaces recursion with a while loop. The logic is identical: enumerate starting pairs, then validate the sequence step by step. Some find this easier to follow than the recursive version.