题意:给定一个字符串,判断能否将其拆分成斐波那契序列,如果可以则输出任意一个。
其中斐波那契序列的num[i]均满足 0 <= num[i] < 2^31
传送门
输入:num = “1101111”
输出:[11,0,11,11]
解释:输出[110,1,111]也可以。
题解一:其实直接暴力就行,枚举序列的前2个数,判断后面的序列是否满足即可,就是写得有点丑。
vector<int> splitIntoFibonacci(string num) {
auto add = [](string a, string b) {
string ret;
if (a.length() < b.length()) swap(a, b);
int flag = 0;
for (int i = 0; i < b.length(); ++i) {
int num = a[a.length()-1-i]-'0'+b[b.length()-1-i]-'0'+flag;
flag = num/10;
num %= 10;
ret = char(num+'0') + ret;
}
for (int i = b.length(); i < a.length(); ++i) {
int num = a[a.length()-1-i]-'0'+flag;
flag = num/10;
num %= 10;
ret = char(num+'0') + ret;
}
if (flag) ret = char(flag+'0') + ret;
return ret;
};
int len = num.length();
vector<int> ret;
function<bool(string,string,int)> is_f = [&](string a, string b, int id){
if (id == len) return true;
if (ret.empty()) {
ret.push_back(stoi(a));
ret.push_back(stoi(b));
}
string sum = add(a, b);
long isum = stol(sum), ia = stol(a), ib = stol(b);
if (isum > INT_MAX || ia > INT_MAX || ib > INT_MAX) return false;
ret.push_back(isum);
int i = id, j = 0;
for (; i < len && j < sum.length(); ++i, ++j) {
if (sum[j] != num[i]) break;
}
if (j < sum.length()) return false;
return is_f(b, sum, i);
};
for (int i = 1; i < len-2; ++i) {
string a = num.substr(0, i);
if (stol(a) > INT_MAX) break;
if (num[i] == '0') {
if (is_f(a, "0", i+1))
return ret;
ret.clear();
continue;
}
for (int j = i; j < len-1; ++j) {
string b = num.substr(i, j-i+1);
if (stol(b) > INT_MAX) break;
if (is_f(a, b, j+1))
return ret;
ret.clear();
}
if (num[0] == '0') break;
}
return ret;
}
题解二:回溯,直接递归,代码短好多,也好看一点
backtrack(id, sum, prev)表示当前从下标id开始,找到和为sum的数,且上一个数为prev;
- 如果存在和为sum的数,则push_back这个sum,然后从sum的下一个下标开始,下一步找sum+prev的数;
- 如果不存在,直接退出,返回false并且回溯(pop_back);
vector<int> splitIntoFibonacci(string num) {
int len = num.length();
vector<int> ret;
function<bool(int,long,int)> backtrack = [&](int id, long sum, int prev){
if (id == len) return ret.size() >= 3;
long cur = 0;
for (int i = id; i < len; ++i) {
cur = cur * 10 + num[i] - '0';
if (cur > INT_MAX)
break;
if (ret.size() >= 2) {
if (cur < sum) continue;
if (cur > sum) break;
}
ret.push_back(cur);
if (backtrack(i+1, prev+cur, cur))
return true;
ret.pop_back();
if (num[id] == '0') break;
}
return false;
};
backtrack(0, 0, 0);
return ret;
}