字符串拆分成数组_#842将数组拆分成斐波那契数列

这个 星期六要考四级,真的是花36块钱体验下卷子。上次去华南理工比数学竞赛,没想到成功混了一个一等奖20a6b2b68d62dd109a7f97bc692a3d8e.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. 两个数字相加,和的长度不会超过两个数中的最大长度+1。

  2. 因为题目给定了整数的范围2^31-1即 2147483647,所以枚举的数字长度不会超过10位。

  3. 斐波那契数列至少要有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)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值