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 |
|