给定一个数字字符串 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]

示例 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. 1 <= S.length <= 200
  2. 字符串 S 中只含有数字。

解法一:回溯

真正回溯的只有前两个数字。当len(ans) > 2时,后续的递归只是检查后续数字是否符合fib。

  1. class Solution:
  2. def splitIntoFibonacci(self, S: str) -> List[int]:
  3. def backtrack(index: int, n: int, ans: List[int]):
  4. if index == n:
  5. return len(ans) >= 3
  6. curr = 0
  7. for i in range(index, n):
  8. if i > index and S[index] == "0":
  9. break
  10. curr = curr * 10 + ord(S[i]) - ord("0")
  11. if curr > 2**31 - 1:
  12. break
  13. if len(ans) < 2 or curr == ans[-2] + ans[-1]:
  14. ans.append(curr)
  15. if backtrack(i + 1, n, ans):
  16. return True
  17. ans.pop()
  18. elif len(ans) > 2 and curr > ans[-2] + ans[-1]:
  19. break
  20. return False
  21. ans = []
  22. backtrack(0, len(S), ans)
  23. return ans
  1. class Solution {
  2. public List<Integer> splitIntoFibonacci(String S) {
  3. List<Integer> ans = new ArrayList<Integer>();
  4. backtrack(S, 0, S.length(), ans);
  5. return ans;
  6. }
  7. public boolean backtrack(String S, int index, int n, List<Integer> ans) {
  8. if (index == n) {
  9. return ans.size() >= 3;
  10. }
  11. long currLong = 0;
  12. for (int i = index; i < n; i++) {
  13. if (i > index && S.charAt(index) == '0') {
  14. break;
  15. }
  16. currLong = currLong * 10 + S.charAt(i) - '0';
  17. if (currLong > Integer.MAX_VALUE) {
  18. break;
  19. }
  20. int curr = (int) currLong;
  21. if (ans.size() < 2 || curr == ans.get(ans.size() - 1) + ans.get(ans.size() - 2)) {
  22. ans.add(curr);
  23. if (backtrack(S, i + 1, n, ans)) {
  24. return true;
  25. }
  26. ans.remove(ans.size() - 1);
  27. } else if (ans.size() > 2 && curr > ans.get(ans.size() - 1) + ans.get(ans.size() - 2)){
  28. break;
  29. }
  30. }
  31. return false;
  32. }
  33. }