题目:
今天的题目分析起来其实也不算复杂,只不过写代码怎么精炼还需要训练。
思路:
1.首先,与昨天的题目相同,我们不可能一次性控制多个变量,所以我们还是要先确定一个固定的量。
2.这个固定的量怎么确定呢?斐波那契数列需要前两个数字是确定的,那么我们就按照前两个数字(基准数)来划分序列。
3.那么,我们很容易想到,基准数以及后续数字的位数是不确定的,于是就需要去遍历每一个位数,遍历的过程中,自然就会想到需要回溯来确定当前遍历的是几位数以及下一个该遍历的是几位数。
4.而这个返回值是一个列表,所以我们可以用list去存储
5.对于每一次遍历,我们有以下条件需要判断
(1) 拆出的数第一个数字是不是为0,如果是,则放弃此次循环,进入下一次
(2)我们拆出的数需要符合整型(int)的要求
(3)如果列表中至少有 2个数,并且拆分出的数已经大于最后 2 个数的和,就不需要继续尝试拆分了。
于是,我们就有了整体的代码思路
这里附上的是题解的C++代码,因为我自己的代码这个逻辑写了几十行,实在是太丑了。
不过题解代码我还是详细注释了,方便能够看懂
C++代码附带测试:
#include<iostream>
#include<vector>
#include<string>
using namespace std;
class Solution {
public:
vector<int> splitIntoFibonacci(string S) {
vector<int> list;
backtrack(list, S, S.length(), 0, 0, 0);
return list;
}
bool backtrack(vector<int>& list, string S, int length, int index, long long sum, int prev) {//对list是引用传递
if (index == length) {
return list.size() >= 3;//检查list数量是否满足要求
}
long long curr = 0;
for (int i = index; i < length; i++) {//遍历计算符合要求的数字
if (i > index && S[index] == '0') {
break;
}
curr = curr * 10 + S[i] - '0';//对序列逐个增加计算
if (curr > INT_MAX) {
break;
}
if (list.size() >= 2) {//如果至少有两个基准数
if (curr < sum) {//如果小于前两数的和,则继续加位运算
continue;
}
else if (curr > sum) {//如果大于前两数的和,则说明当前序列已经不满足了,直接弹出
break;
}
}
list.push_back(curr);//等于前两数的和,
if (backtrack(list, S, length, i + 1, prev + curr, curr)) {//向下继续遍历
return true;
}
list.pop_back();//弹出最后一个元素(说明这个元素不满足要求,需要加上后一位继续计算)
}
return false;//不满足要求的会返回false
}
};
int main()
{
string s = "123456579";
Solution solution;
vector<int> list = solution.splitIntoFibonacci(s);
for(auto& i:list)
{
cout<<i<<endl;
}
}