0
点赞
收藏
分享

微信扫一扫

【LeetCode】842. 将数组拆分成斐波那契序列


一、题目描述

给定一个数字字符串 S,比如 S = “123456579”,我们可以将它分成斐波那契式的序列 [123, 456, 579]。

形式上,斐波那契式序列是一个非负整数列表 F,且满足:

  1. 0 <= F[i] <= 2^31 - 1,(也就是说,每个整数都符合 32 位有符号整数类型);
    F.length >= 3;
  2. 对于所有的0 <= i < F.length - 2,都有 F[i] + F[i+1] = F[i+2] 成立。
  3. 另外,请注意,将字符串拆分成小块时,每个块的数字一定不要以零开头,除非这个块是数字 0 本身。

返回从 S 拆分出来的任意一组斐波那契式的序列块,如果不能拆分则返回 []。

示例 1:

输入:"123456579"
输出:[123,456,579]

示例 2:

输入: "11235813"
输出: [1,1,2,3,5,8,13]

示例 3:

输入: "112358130"
输出: []
解释: 这项任务无法完成。

示例 4:

输入:"0123"
输出:[]
解释:每个块的数字不能以零开头,因此 "01","2","3" 不是有效答案。

示例 5:

输入: "1101111"
输出: [110, 1, 111]
解释: 输出 [11,0,11,11] 也同样被接受。

提示:

1 <= S.length <= 200
字符串 S 中只含有数字。

二、解题思路 & 代码

2.1 暴力法

想法

数组的前两个元素唯一决定了后面的数组元素。

算法

对于每种可能的前两个元素,假设没有前导零,遍历剩余的字符串。对于每个情况,我们希望得到小于等于 2^31 - 1 的数,且是前两个数字之和。

class Solution(object):
def splitIntoFibonacci(self, S):
for i in xrange(min(10, len(S))):
x = S[:i+1]
if x != '0' and x.startswith('0'): break
a = int(x)
for j in xrange(i+1, min(i+10, len(S))):
y = S[i+1: j+1]
if y != '0' and y.startswith('0'): break
b = int(y)
fib = [a, b]
k = j + 1
while k < len(S):
nxt = fib[-1] + fib[-2]
nxtS = str(nxt)
if nxt <= 2**31 - 1 and S[k:].startswith(nxtS):
k += len(nxtS)
fib.append(nxt)
else:
break
else:
if len(fib) >= 3:
return fib
return []

复杂度分析

  1. 时间复杂度:,其中 N 是 S 的长度,按照要求结果的长度都是 O(1) 的。
  2. 空间复杂度:O(N)。

2.2 回溯 + 剪枝

主要是回溯过程中的剪枝优化,减去了值大于2 ** 31 - 1和不符合F[i] + F[i + 1] = F[i + 2]的部分。还有就是new_value以’0’开头并且长度大于1的部分,需要注意’0’是符合条件的数字。

class Solution:
def splitIntoFibonacci(self, S: str) -> List[int]:
n = len(S)

res = []

def backtrack(index, temp):
if index == n:
if self._is_fibonacci(temp):
res.append(temp)
return

for i in range(index, n):
new_value = S[index:i + 1]
if int(new_value) > 2 ** 31 - 1:
break
if not (new_value.startswith('0') and len(new_value) > 1):
if len(temp) >= 2 and int(new_value) == (temp[-1] + temp[-2]):
backtrack(i + 1, temp + [int(new_value)])
elif len(temp) < 2:
backtrack(i + 1, temp + [int(new_value)])

backtrack(0, [])

return res[0] if res else []

def _is_fibonacci(self, temp):
if len(temp) < 3:
return False
for i in range(2, len(temp)):
if temp[i] != (temp[i - 1] + temp[i - 2]):
return False

return True

参考:

  1. ​​LeetCode 官方题解​​
  2. ​​LeetCode题解​​


举报

相关推荐

0 条评论