累加数是一个字符串,组成它的数字可以形成累加序列。
一个有效的累加序列必须至少包含 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
进阶:
你如何处理一个溢出的过大的整数输入?
思路:对于这类把输入字符串进行切分,然后看是否满足某种规律的题目可以参考Palindrome Partitioning 分割回文串的通用公式,注意这和组合的情况的不一样,组合是从n个中选择m个,剩下的n-m个就不用了,和这种把一个字符串进行划分的还不一样。下面先给出通用公式:
void partitionCore(vector<vector<string>> &res, vector<string> &curStr, string &s ,int start) {
if (start == (s.size())) {
res.push_back(curStr);
}
for (int i = start; i < s.size(); i++) {
if (isPlidrom(s, start, i)) {
curStr.push_back(s.substr(start,(i-start+1)));
partitionCore(res, curStr, s, i + 1);
curStr.pop_back();
}
}
}
这部分是核心代码,在递归的开始部分先做判断:如果当前的下标start到了给定字符串的长度,就做blabla。。。然后从i=start开始,一直遍历到s的长度,在每次遍历过程中,我们都需要先把字符串从start~i(包括i)进行切割,然后放入临时字符串中,观察临时字符串是否满足某种规律,如果满足就把当前临时字符串放入结果中。
那么同理,我们用上面的模板来套这道题,只不过多了几个判断。
1因为只要满足一个条件就可以,所以我们在参数中设置一个引用bool的flag,如果找到的话直接返回结果,不再寻找。
2由于要满足斐波那契的规律:G(n-2)+G(n-1)=G(n),所以我们需要一个数组来存储已经找到的数字,而且还需要处理大数字的问题,所以需要几个辅助函数:
2.1判断数组的最后两个数字和新数字cur是否满足规律:G(n-2)+G(n-1)=G(n)
bool isSequece(vector<long long int> &res,long long int cur)
2.2判断一个字符串是否是无效字符串,主要是01,02这样有前导0的
bool isvalid(string &str)
2.3把一个string转为long long int(为了避免数字溢出,用long long int类型)
long long int string_int(string &str)
最后看核心代码:
void isAdditiveNumber(vector<long long int> &res, string &num, bool &flag, int start) {
if (flag || start == num.size()) {
if (res.size() >= 3) {
flag = true;
}
return;
}
for (int i = start; i < num.size(); i++) {
string sub = (num.substr(start, i - start + 1));
if (!isvalid(sub)) break;
long long int temp = string_int(sub);
if (res.size() < 2) {
res.push_back(temp);
isAdditiveNumber(res,num,flag,i+1);
res.pop_back();
}
else {
if (isSequece(res, temp)) {
res.push_back(temp);
isAdditiveNumber(res, num, flag, i + 1);
res.pop_back();
}
}
if (flag) return;
}
}
这里有分叉处理,如果当前res的长度小于2,那么先放进去res中(因为规律必须要至少3个数才能判断),最后加了剪纸判断,如果已经找到了直接返回true,不再继续寻找。
参考代码:
class Solution {
public:
bool isSequece(vector<long long int> &res,long long int cur) {
if (res.size() >= 2) {
if ((res[res.size() - 1] + res[res.size() - 2]) == cur) {
return true;
}
}
return false;
}
bool isvalid(string &str) {
if ((str.size() > 1) && str[0] == '0') return false;
return true;
}
long long int string_int(string &str) {
long long int res = 0;
for (int i = 0; i < str.size(); i++) {
res = res * 10 + (str[i] - '0');
}
return res;
}
void isAdditiveNumber(vector<long long int> &res, string &num, bool &flag, int start) {
if (flag || start == num.size()) {
if (res.size() >= 3) {
flag = true;
}
return;
}
for (int i = start; i < num.size(); i++) {
string sub = (num.substr(start, i - start + 1));
if (!isvalid(sub)) break;
long long int temp = string_int(sub);
if (res.size() < 2) {
res.push_back(temp);
isAdditiveNumber(res,num,flag,i+1);
res.pop_back();
}
else {
if (isSequece(res, temp)) {
res.push_back(temp);
isAdditiveNumber(res, num, flag, i + 1);
res.pop_back();
}
}
if (flag) return;
}
}
bool isAdditiveNumber(string num) {
bool flag = false;
vector<long long int> res;
isAdditiveNumber(res, num, flag,0);
return flag;
}
};