题目:
累加数是一个字符串,组成它的数字可以形成累加序列。
一个有效的累加序列必须至少包含 3 个数。除了最开始的两个数以外,字符串中的其他数都等于它之前两个数相加的和。
给定一个只包含数字 '0'-'9' 的字符串,编写一个算法来判断给定输入是否是累加数。
说明: 累加序列里的数不会以 0 开头,所以不会出现 1, 2, 03 或者 1, 02, 3 的情况。
示例 1:
输入: "112358"
输出: true
解释: 累加序列为: 1, 1, 2, 3, 5, 8 。1 + 1 = 2, 1 + 2 = 3, 2 + 3 = 5, 3 + 5 = 8
示例 2:
输入: "199100199"
输出: true
解释: 累加序列为: 1, 99, 100, 199。1 + 99 = 100, 99 + 100 = 199
进阶:
你如何处理一个溢出的过大的整数输入?
来源:
解题思路:回溯
此题与将数字字符串拆分成斐波那契序列类似,不同的是此题返回bool类型,并且数字很大。
定义一个数组path,记录拆分的数字。
- 递归终止条件:字符串拆分完成并且至少拆分3个数字
- 剪枝条件:有一个完成时,或者第一个数字放入时,如果其长度超过字符串一半肯定不能拆分,或者前2个数字和小于当前数字n时。
class Solution {
public:
vector<long> path;
bool finish;
bool isAdditiveNumber(string S) {
finish = false;
// 处理开头的0
int start = 0;
while (start < S.size() && S[start] == '0') {
path.push_back(0);
start++;
}
back(S, start);
return finish;
}
void back(const string& s, int start) {
if (path.size() > 2 && start == s.size()) {
finish = true;
return;
}
// 处理开头的0
if (s[start] == '0') {
if (path.size() < 2) {
path.push_back(0);
back(s, start + 1);
path.pop_back();
}
return;
}
long n = 0;
for (int i = start; i < s.size(); i++) {
if (finish) break;
int sz = path.size();
if ((sz == 0 && i >= s.size()/2) ||
(sz > 1 && path[sz-1] + path[sz-2] < n)) break;
n = n * 10 + s[i] - '0'; // n:[start,i]内的数字
if (sz < 2 || path[sz-1] + path[sz-2] == n) {
path.push_back(n);
back(s, i + 1);
path.pop_back();
}
}
}
};