Problem#
You are given a string of digits num
, such as "123456579"
. We can split it into a Fibonacci-like sequence [123, 456, 579]
.
Formally, a Fibonacci-like sequence is a list f
of non-negative integers such that:
0 <= f[i] < 231
, (that is, each integer fits in a 32-bit signed integer type),
f.length >= 3
, and
f[i] + f[i + 1] == f[i + 2]
for all 0 <= i < f.length - 2
.
Note that when splitting the string into pieces, each piece must not have extra leading zeroes, except if the piece is the number 0
itself.
Return any Fibonacci-like sequence split from num
, or return []
if it cannot be done.
Examples#
Example 1#
1
2
3
Input: num = "1101111"
Output: [ 11 , 0 , 11 , 11 ]
Explanation: The output [ 110 , 1 , 111 ] would also be accepted.
Example 2#
1
2
3
Input: num = "112358130"
Output: []
Explanation: The task is impossible.
Example 3#
1
2
3
Input: num = "0123"
Output: []
Explanation: Leading zeroes are not allowed, so "01" , "2" , "3" is not valid.
Constraints#
1 <= num.length <= 200
num
contains only digits.
Solution#
Method 1 – Backtracking#
Intuition#
Try all possible ways to split the string into numbers, and build the sequence step by step. At each step, check if the next number matches the sum of the previous two. If so, continue; otherwise, backtrack. Handle leading zeros and integer overflow as constraints.
Approach#
Use backtracking to try every possible split of the string into numbers.
For each split, check:
No number has leading zeros unless it is ‘0’.
Each number fits in a 32-bit signed integer.
The sequence follows the Fibonacci property: f[i] + f[i+1] == f[i+2].
If a valid sequence of length at least 3 is found, return it.
If no valid sequence exists, return an empty list.
Code#
Cpp
Go
Java
Kotlin
Python
Rust
Typescript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Solution {
public :
vector< int > splitIntoFibonacci(string num) {
vector< int > ans;
dfs(num, 0 , ans);
return ans.size() >= 3 ? ans : vector< int > {};
}
bool dfs (const string& s, int idx, vector< int >& ans) {
if (idx == s.size()) return ans.size() >= 3 ;
long long n = 0 ;
for (int i = idx; i < s.size(); ++ i) {
if (i > idx && s[idx] == '0' ) break ;
n = n * 10 + s[i] - '0' ;
if (n > INT_MAX) break ;
if (ans.size() < 2 || n == (long long )ans[ans.size()- 1 ] + ans[ans.size()- 2 ]) {
ans.push_back(n);
if (dfs(s, i+ 1 , ans)) return true;
ans.pop_back();
}
}
return false;
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
func splitIntoFibonacci (num string ) []int {
var ans []int
var dfs func (idx int ) bool
dfs = func (idx int ) bool {
if idx == len(num ) {
return len(ans ) >= 3
}
n := 0
for i := idx ; i < len(num ); i ++ {
if i > idx && num [idx ] == '0' {
break
}
n = n * 10 + int(num [i ]- '0' )
if n > 1 << 31 - 1 {
break
}
if len(ans ) < 2 || n == ans [len(ans )- 1 ]+ ans [len(ans )- 2 ] {
ans = append(ans , n )
if dfs (i + 1 ) {
return true
}
ans = ans [:len(ans )- 1 ]
}
}
return false
}
dfs (0 )
if len(ans ) >= 3 {
return ans
}
return []int {}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution {
public List< Integer> splitIntoFibonacci (String num) {
List< Integer> ans = new ArrayList<> ();
dfs(num, 0, ans);
return ans.size () >= 3 ? ans : new ArrayList<> ();
}
boolean dfs (String s, int idx, List< Integer> ans) {
if (idx == s.length ()) return ans.size () >= 3;
long n = 0;
for (int i = idx; i < s.length (); ++ i) {
if (i > idx && s.charAt (idx) == '0' ) break ;
n = n * 10 + s.charAt (i) - '0' ;
if (n > Integer.MAX_VALUE ) break ;
if (ans.size () < 2 || n == (long )ans.get (ans.size ()- 1) + ans.get (ans.size ()- 2)) {
ans.add ((int )n);
if (dfs(s, i+ 1, ans)) return true ;
ans.remove (ans.size ()- 1);
}
}
return false ;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution {
fun splitIntoFibonacci (num: String): List<Int> {
val ans = mutableListOf<Int>()
fun dfs (idx: Int): Boolean {
if (idx == num.length) return ans.size >= 3
var n = 0L
for (i in idx until num.length) {
if (i > idx && num[idx] == '0' ) break
n = n * 10 + (num[i] - '0' )
if (n > Int .MAX_VALUE) break
if (ans.size < 2 || n == ans[ans.size-1 ].toLong() + ans[ans.size-2 ].toLong()) {
ans.add(n.toInt())
if (dfs(i+1 )) return true
ans.removeAt(ans.size-1 )
}
}
return false
}
dfs(0 )
return if (ans.size >= 3 ) ans else emptyList()
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def splitIntoFibonacci (num: str) -> list[int]:
def backtrack (idx: int, ans: list[int]) -> bool:
if idx == len(num):
return len(ans) >= 3
n = 0
for i in range(idx, len(num)):
if i > idx and num[idx] == '0' :
break
n = n * 10 + int(num[i])
if n > 2 ** 31 - 1 :
break
if len(ans) < 2 or n == ans[- 1 ] + ans[- 2 ]:
ans. append(n)
if backtrack(i+ 1 , ans):
return True
ans. pop()
return False
ans = []
backtrack(0 , ans)
return ans if len(ans) >= 3 else []
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
impl Solution {
pub fn split_into_fibonacci (num: String) -> Vec< i32 > {
fn dfs (s: & str , idx: usize , ans: & mut Vec< i32 > ) -> bool {
if idx == s.len() { return ans.len() >= 3 ; }
let mut n: i64 = 0 ;
for i in idx.. s.len() {
if i > idx && & s[idx.. idx+ 1 ] == "0" { break ; }
n = n * 10 + (s[i.. i+ 1 ].parse::< i64 > ().unwrap());
if n > i32 ::MAX as i64 { break ; }
if ans.len() < 2 || n == ans[ans.len()- 1 ] as i64 + ans[ans.len()- 2 ] as i64 {
ans.push(n as i32 );
if dfs(s, i+ 1 , ans) { return true ; }
ans.pop();
}
}
false
}
let mut ans = Vec::new();
dfs(& num, 0 , & mut ans);
if ans.len() >= 3 { ans } else { vec! [] }
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution {
splitIntoFibonacci (num : string ): number [] {
const ans : number [] = [];
function dfs (idx : number ): boolean {
if (idx === num .length ) return ans .length >= 3 ;
let n = 0 ;
for (let i = idx ; i < num .length ; ++ i ) {
if (i > idx && num [idx ] === '0' ) break ;
n = n * 10 + Number(num [i ]);
if (n > 2 ** 31 - 1 ) break ;
if (ans .length < 2 || n === ans [ans .length - 1 ] + ans [ans .length - 2 ]) {
ans .push (n );
if (dfs (i + 1 )) return true ;
ans .pop ();
}
}
return false ;
}
dfs (0 );
return ans .length >= 3 ? ans : [];
}
}
Complexity#
⏰ Time complexity: O(2^n)
– Backtracking tries all splits, but prunes invalid ones early.
🧺 Space complexity: O(n)
– Space for the answer sequence and recursion stack.