这个
星期六要考四级,真的是花36块钱体验下卷子。上次去华南理工比数学竞赛,没想到成功混了一个一等奖
这道题我是真的不会,一直知道斐波那契问题应该使用回溯法+剪枝,奈何自己还没学到那,思维跟不上,想到死也解不出来。
首先
来看看题目:
![20a6b2b68d62dd109a7f97bc692a3d8e.png](https://i-blog.csdnimg.cn/blog_migrate/d3909c160f046216ed5734a8a748a96e.png)
给定一个数字字符串 S,比如 S = "123456579",我们可以将它分成斐波那契式的序列 [123, 456, 579]。形式上,斐波那契式序列是一个非负整数列表 F,且满足:0 <= F[i] <= 2^31 - 1,(也就是说,每个整数都符合 32 位有符号整数类型);F.length >= 3;对于所有的0 <= i < F.length - 2,都有 F[i] + F[i+1] = F[i+2] 成立。另外,请注意,将字符串拆分成小块时,每个块的数字一定不要以零开头,除非这个块是数字 0 本身。返回从 S 拆分出来的任意一组斐波那契式的序列块,如果不能拆分则返回 []。
示例 1:输入:"123456579"输出:[123,456,579]
简单明了,给定一个字符串,你需要将其拆分成斐波那契数列
,如果无法拆分则返回 [ ] 。
我们知道斐波那契数列满足:除了第一个数和第二个数以外
,列表中的每个数字都等于前两个数字的和。
于是,我们去枚举第一个数和第二个数,然后把他们俩加起来,判断是否等于枚举出的第三个,如果等于,就把第三个数加入到答案中来,并去判断第四个数是否符合斐波那契数列,否则退回第二个数,继续枚举。
若第二个数也枚举完了,但还无法满足斐波那契数列,则退回到第一个数,即继续枚举第一个数。这说明回溯改变的是前两个数字,只有当前两个数字确定了,后面所有的数都将确定。
需要说明的是:
两个数字相加,和的长度不会超过两个数中的最大长度+1。
因为题目给定了整数的范围2^31-1即 2147483647,所以枚举的数字长度不会超过10位。
斐波那契数列至少要有3个数字,且前两个数字相加等于第三个数,所以一个字串的长度不会超过(n-1)//2
def splitIntoFibonacci(S): n,up = len(S),2147483647 for i in range(1,11):#最大数值长度不超过10个 for j in range(1,min(11,n-i)):#控制步长 ans = [int(S[:i]),int(S[i:i+j])] print(ans,(i,j)) if helper(i+j): return ans if S[i] == '0': break if S[0] == '0': break return []
def helper(start): if max(ans) > up:return False while start < n: now = ans[-1] + ans[-2] c = len(str(now)) if now > up or start + c > n or int(S[start:start+c]) != now: return False ans.append(now) start += c return True
因为题目规定了最大整数不超过2147483647
,所以为了方便后续的判断,将其赋值给up变量;
于是我们开始枚举第一个和第二个数,注意最大值的长度不超过10个,因此遍历第一个数只需要
range(1,11)
,第二个数的长度一定小于n-第一个数字的长度,因此遍历第二个数只需要range(1,min(11,n-i))
,于是就确定了前两个数字。
完成这些后,借助helper函数去确定第三个数,因为第二个数的范围使用了S[i:i+j]
所以,枚举第三个数字时就应该从i+j开始。
对于helper函数来说,我们记第一个数+第二个数为now变量;若
第三个数满足斐波那契数列
,所以
第三个数的长度一定等于now的长度。所以只需取S的切片S[start:start+c],判断其是否等于now。如果等于,说明前两个数和第三个数已确定,记下来去查找第四个数是否满足条件;如果不等于,则说明第二个数枚举的不对,继续枚举。
可以在循环的时候打印print(ans,(i,j))
,(以S="123456579")如下所示:
[1, 2] (1, 1)[1, 23] (1, 2)[1, 234] (1, 3)[1, 2345] (1, 4)[1, 23456] (1, 5)[1, 234565] (1, 6)[1, 2345657] (1, 7)[12, 3] (2, 1)[12, 34] (2, 2)[12, 345] (2, 3)[12, 3456] (2, 4)[12, 34565] (2, 5)[12, 345657] (2, 6)[123, 4] (3, 1)[123, 45] (3, 2)[123, 456] (3, 3)