题目描述
给定一个数字字符串 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 拆分出来的任意一组斐波那契式序列,不能拆分则返回 []。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/split-array-into-fibonacci-sequence
思路
- 回溯:
-
声明一个数组来保存回溯过程(遍历字符串中所有可能的当前被拆分的数字情况,再继续拆分剩余字符串)中满足条件的数。满足以下条件时将数字保存进数组
(1)若数组为空或者数字个数为1,则直接保存进数组
(2)若数组数字个数大于等于2,则新拆分的数等于数组最后看两个数的和时,将新拆分的数保存进数组
- 剪枝:
-
以下情况可以直接停止此次拆分:
(1)新拆分的数若以‘0’开头,且不是0
(2)新拆分的数超过2^31-1
(3)数组数字个数大于等于2,则新拆分的数大于数组最后看两个数的和
代码(CPP)
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class Solution {
vector<int> res;
public:
vector<int> splitIntoFibonacci(string S) {
back(S, 0, 0, 0);
return res;
}
bool back(string S, int sum, int pre, int index) {
//结束回溯
if (index == S.length()) {
bool hasRes = (res.size() >= 3);
return hasRes;
}
//当前的数字,声明为long检测int溢出
long curNum = 0;
for (int i = index; i < S.length(); i++) {
//检测溢出
curNum = curNum * 10 + S[i] - '0';
if (curNum > INT_MAX) {
return false;
}
//以'0'开头的新数字只能是0
if (S[index] == '0' && i != index) {
return false;
}
if (res.size() >= 2) {
//当前的数字比其前两个数字的和大,不满足;小则继续增添该数
if (curNum > sum) {
return false;
}
else if(curNum < sum){
continue;
}
}
//当前的数字比其前等于两个数字的和或者当前答案数组中的数字个数小于2,将其加入答案数组
res.push_back(((int)curNum));
if (back(S, curNum + pre, curNum, i + 1)) {
return true;
}
res.pop_back();
}
return false;
}
};
int main() {
string S = "123456579";
Solution* s = new Solution();
vector<int> res = s->splitIntoFibonacci(S);
}