Given a string num
containing only digits, the task is to split it into a sequence of integers to form a Fibonacci-like sequence. A Fibonacci-like sequence is a list of numbers where each number is the sum of the two preceding ones (i.e., F[i] = F[i-1] + F[i-2]
for all i >= 2
).
The requirements are:
<= 2^31 - 1
).num
must be used, and no digit can be reused or left over.At first glance, the problem seems to be about splitting the string in all possible ways and checking if any sequence forms a Fibonacci-like sequence. This hints at a brute-force or backtracking approach, since there are many ways to split the string.
However, we quickly realize that:
The solution can be broken down into the following steps:
This approach is efficient because:
Let's consider the input num = "11235813"
.
1
(index 0), second number 1
(index 1).2
. The next digit is 2
(index 2) — matches.3
. Next digit is 3
(index 3) — matches.5
. Next digit is 5
(index 4) — matches.8
. Next digit is 8
(index 5) — matches.13
. Next two digits are 1
and 3
(index 6-7) — matches.If at any point the next number does not match the corresponding substring, we backtrack and try a different split for the first or second number.
Brute-force approach:
num
.num
.This is efficient for reasonable input sizes.
The key insight is that once the first two numbers are chosen, the rest of the Fibonacci sequence is uniquely determined. By systematically trying all possible splits for the first two numbers and greedily checking the rest, we can efficiently find (or rule out) a valid sequence. The solution is elegant because it leverages the deterministic nature of the Fibonacci sequence and avoids unnecessary recursion or brute-force exploration.
class Solution:
def splitIntoFibonacci(self, S: str):
n = len(S)
for i in range(1, min(10, n)):
if S[0] == '0' and i > 1:
break
a = int(S[:i])
if a > 2**31 - 1:
break
for j in range(i+1, min(i+10, n)):
if S[i] == '0' and j - i > 1:
break
b = int(S[i:j])
if b > 2**31 - 1:
break
fib = [a, b]
k = j
while k < n:
nxt = fib[-1] + fib[-2]
if nxt > 2**31 - 1:
break
nxt_str = str(nxt)
if not S.startswith(nxt_str, k):
break
fib.append(nxt)
k += len(nxt_str)
if k == n and len(fib) >= 3:
return fib
return []
class Solution {
public:
vector<int> splitIntoFibonacci(string S) {
int n = S.size();
for (int i = 1; i < min(10, n); ++i) {
if (S[0] == '0' && i > 1) break;
long a = stol(S.substr(0, i));
if (a > INT_MAX) break;
for (int j = i+1; j < min(i+10, n); ++j) {
if (S[i] == '0' && j - i > 1) break;
long b = stol(S.substr(i, j-i));
if (b > INT_MAX) break;
vector<int> fib = { (int)a, (int)b };
int k = j;
while (k < n) {
long nxt = (long)fib[fib.size()-1] + fib[fib.size()-2];
if (nxt > INT_MAX) break;
string nxt_str = to_string(nxt);
if (S.substr(k, nxt_str.size()) != nxt_str) break;
fib.push_back((int)nxt);
k += nxt_str.size();
}
if (k == n && fib.size() >= 3) return fib;
}
}
return {};
}
};
class Solution {
public List<Integer> splitIntoFibonacci(String S) {
int n = S.length();
for (int i = 1; i < Math.min(10, n); i++) {
if (S.charAt(0) == '0' && i > 1) break;
long a = Long.parseLong(S.substring(0, i));
if (a > Integer.MAX_VALUE) break;
for (int j = i+1; j < Math.min(i+10, n); j++) {
if (S.charAt(i) == '0' && j - i > 1) break;
long b = Long.parseLong(S.substring(i, j));
if (b > Integer.MAX_VALUE) break;
List<Integer> fib = new ArrayList<>();
fib.add((int)a);
fib.add((int)b);
int k = j;
while (k < n) {
long nxt = (long)fib.get(fib.size()-1) + fib.get(fib.size()-2);
if (nxt > Integer.MAX_VALUE) break;
String nxtStr = String.valueOf(nxt);
if (!S.startsWith(nxtStr, k)) break;
fib.add((int)nxt);
k += nxtStr.length();
}
if (k == n && fib.size() >= 3) return fib;
}
}
return new ArrayList<>();
}
}
var splitIntoFibonacci = function(S) {
const n = S.length;
for (let i = 1; i < Math.min(10, n); i++) {
if (S[0] === '0' && i > 1) break;
let a = Number(S.slice(0, i));
if (a > 2**31 - 1) break;
for (let j = i+1; j < Math.min(i+10, n); j++) {
if (S[i] === '0' && j - i > 1) break;
let b = Number(S.slice(i, j));
if (b > 2**31 - 1) break;
let fib = [a, b];
let k = j;
while (k < n) {
let nxt = fib[fib.length-1] + fib[fib.length-2];
if (nxt > 2**31 - 1) break;
let nxtStr = nxt.toString();
if (S.slice(k, k + nxtStr.length) !== nxtStr) break;
fib.push(nxt);
k += nxtStr.length;
}
if (k === n && fib.length >= 3) return fib;
}
}
return [];
};