|
| 1 | +# Additive Number |
| 2 | + |
| 3 | +An additive number is a string whose digits can form an additive sequence. |
| 4 | + |
| 5 | +A valid additive sequence should contain at least three numbers. Except for the first two numbers, each subsequent |
| 6 | +number in the sequence must be the sum of the preceding two. |
| 7 | + |
| 8 | +Given a string containing only digits, return true if it is an additive number or false otherwise. |
| 9 | + |
| 10 | +> Note: Numbers in the additive sequence cannot have leading zeros, so sequence 1, 2, 03 or 1, 02, 3 is invalid. |
| 11 | +
|
| 12 | +## Examples |
| 13 | + |
| 14 | +Example 1: |
| 15 | +```text |
| 16 | +Input: "112358" |
| 17 | +Output: true |
| 18 | +Explanation: |
| 19 | +The digits can form an additive sequence: 1, 1, 2, 3, 5, 8. |
| 20 | +1 + 1 = 2, 1 + 2 = 3, 2 + 3 = 5, 3 + 5 = 8 |
| 21 | +``` |
| 22 | + |
| 23 | +Example 2: |
| 24 | +```text |
| 25 | +Input: "199100199" |
| 26 | +Output: true |
| 27 | +Explanation: |
| 28 | +The additive sequence is: 1, 99, 100, 199. |
| 29 | +1 + 99 = 100, 99 + 100 = 199 |
| 30 | +``` |
| 31 | + |
| 32 | +## Constraints |
| 33 | + |
| 34 | +- 1 <= num.length <= 35 |
| 35 | +- num consists only of digits. |
| 36 | + |
| 37 | +## Topics |
| 38 | + |
| 39 | +- String |
| 40 | +- Backtracking |
| 41 | + |
| 42 | +## Solution |
| 43 | + |
| 44 | +The key intuition behind this problem is that once we fix the first two numbers in the sequence, the entire rest of the |
| 45 | +sequence is completely determined, each subsequent number must equal the sum of the two preceding ones. Therefore, we |
| 46 | +use backtracking to try all possible ways to choose the first and second numbers by varying their lengths, and for each |
| 47 | +choice, we greedily verify whether the remaining digits of the string can be partitioned to satisfy the additive property. |
| 48 | +The backtrack function processes the string from left to right, extracting candidate numbers of increasing length. For |
| 49 | +the first two numbers (count < 2), we freely explore all possible lengths. Once we have at least two numbers, we compute |
| 50 | +the `expectedSum` and prune: if `currentNum` exceeds `expectedSum`, we break (longer substrings will only be larger); if |
| 51 | +`currentNum` is less, we continue to try a longer substring. If `currentNum` matches, we recurse deeper. The recursion |
| 52 | +succeeds when we consume the entire string with at least 3 numbers in the sequence. |
| 53 | + |
| 54 | +Now, let's look at the solution steps below: |
| 55 | + |
| 56 | +1. Initialize n as the length of the input string num. |
| 57 | +2. Define a recursive helper function `backtrack(start, prev1, prev2, count)` where `start` is the current index in `num`, |
| 58 | + `prev1` is the second-to-last number, `prev2` is the last number, and count tracks how many numbers have been placed |
| 59 | + so far. |
| 60 | +3. **Base case**: If `start` equals `n` (the entire string has been consumed), return true if count ≥ 3, otherwise return |
| 61 | + false. |
| 62 | +4. Iterate over all possible end positions `end` from `start + 1` to `n` (inclusive) to form candidate substrings |
| 63 | + `num[start:end]`. |
| 64 | + - If the substring has length greater than 1 and starts with '0', break out of the loop — this handles the leading-zero |
| 65 | + constraint, since any longer substring starting from the same position will also have a leading zero. |
| 66 | + - Convert the `substring` to an integer `currentNum`. |
| 67 | + - If `count ≥ 2` (meaning we already have at least two numbers), compute `expectedSum` as `prev1 + prev2`. |
| 68 | + - If `currentNum` > `expectedSum`, break as no need to try longer substrings since they will only yield larger values. |
| 69 | + - If `currentNum` < `expectedSum`, continue and try a longer substring that might match the expected sum. |
| 70 | + - If `currentNum` = `expectedSum`, proceed to recurse. |
| 71 | + - Recursively call `backtrack(end, prev2, currentNum, count + 1)`. If it returns true, propagate true upward immediately. |
| 72 | +5. If no valid partition is found after exhausting all candidates, return false. |
| 73 | +6. Invoke backtrack(0, 0, 0, 0) and return its result. |
| 74 | + |
| 75 | +### Time Complexity |
| 76 | + |
| 77 | +The time complexity is commonly described as O(n^3): O(n^2) choices for the first two numbers, and O(n) to validate the |
| 78 | ++rest for each choice. If you also account for substring-to-integer parsing cost, the practical bound can be higher. |
| 79 | + |
| 80 | +> Note that Python natively handles arbitrarily large integers, which addresses the follow-up question about overflow |
| 81 | +> for very large inputs, no special handling is needed. |
| 82 | +
|
| 83 | +### Space Complexity |
| 84 | + |
| 85 | +The space complexity of the solution is O(n) because the recursion depth is at most O(n) (in the case where each number |
| 86 | +is a single digit), and each recursive call uses a constant amount of additional space aside from the call stack. |
| 87 | +Substring creation also uses up to O(n) space. |
0 commit comments