842. 将数组拆分成斐波那契序列
题目描述
给定一个数字字符串 num
,比如 "123456579"
,我们可以将它分成「斐波那契式」的序列 [123, 456, 579]
。
形式上,斐波那契式 序列是一个非负整数列表 f
,且满足:
0 <= f[i] < 231
,(也就是说,每个整数都符合 32 位 有符号整数类型)f.length >= 3
- 对于所有的
0 <= i < f.length - 2
,都有f[i] + f[i + 1] = f[i + 2]
另外,请注意,将字符串拆分成小块时,每个块的数字一定不要以零开头,除非这个块是数字 0
本身。
返回从 num
拆分出来的任意一组斐波那契式的序列块,如果不能拆分则返回 []
。
示例 1:
输入:num = "1101111" 输出:[11,0,11,11] 解释:输出 [110,1,111] 也可以。
示例 2:
输入: num = "112358130" 输出: [] 解释: 无法拆分。
示例 3:
输入:"0123" 输出:[] 解释:每个块的数字不能以零开头,因此 "01","2","3" 不是有效答案。
提示:
1 <= num.length <= 200
num
中只含有数字
解法
方法一:回溯 + 剪枝
我们设计一个函数 \(dfs(i)\),表示从字符串 \(num\) 的第 \(i\) 个字符开始拆分,拆分出的斐波那契式序列是否满足题目要求。如果满足,我们就返回 \(true\),否则返回 \(false\)。
函数 \(dfs(i)\) 的具体实现如下:
如果 \(i\) 等于字符串 \(num\) 的长度,说明我们已经拆分完整个字符串,此时我们只需要判断拆分出的序列的长度是否大于 \(2\) 即可。如果大于 \(2\),说明我们找到了一组满足题目要求的斐波那契式序列,返回 \(true\);否则返回 \(false\)。
如果 \(i\) 小于字符串 \(num\) 的长度,我们需要枚举拆分出的第一个数 \(x\),如果 \(x\) 的长度大于 \(1\),且以 \(0\) 开头,说明 \(x\) 不是一个合法的数,我们直接返回 \(false\)。否则我们将 \(x\) 转换成十进制数,如果 \(x\) 大于 \(2^{31} - 1\),或者 \(x\) 大于 \(ans\) 的最后两个数之和,直接返回 \(false\)。如果 \(ans\) 的长度小于 \(2\),或者 \(x\) 等于 \(ans\) 的最后两个数之和,我们将 \(x\) 加入到 \(ans\) 中,然后继续拆分字符串 \(num\) 的后面的部分,如果返回 \(true\),说明我们找到了一组满足题目要求的斐波那契式序列,返回 \(true\);否则我们将 \(x\) 从 \(ans\) 中移除,然后继续枚举拆分出的第一个数 \(x\)。
时间复杂度 \(O(n \times \log^2 M)\),空间复杂度 \(O(n)\)。其中 \(n\) 和 \(M\) 分别是字符串 \(num\) 的长度和整型数的最大值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
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 33 34 35 |
|
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 |
|
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 |
|