题目
思路一 回溯+高精度
把string和string的长度都变成全局变量。判断每一位数据的所有存储可能性,如果当前位是u,u=n时,如果vector中有三个或三个以上数据就返回true。再根据u位的数据进行下一步判断,u位的数不为0时,最长的位是n;u位的数为0时,最长的位就是u+1.再针对每个可能的位逐步判断,如果当前数据个数小于2就都可以放进去,如果大于等于2就需要考虑这个数是否等于前两个数之和。循环中先把这种情况的数据放入vector,进而判断下一步是否满足条件,如果满足就返回true,如果不满足就把刚刚放入的数据pop出来。
由于数据可能超出范围,所以每个数据用vector存储。对a+b=c的检查也需要把a、b和c放到vector中,逐位相加再判断。
代码一
class Solution {
public:
string num;
int n;
vector<vector<int>> v;
bool isAdditiveNumber(string _num) {
num=_num;
n=_num.size();
return dfs(0);
}
bool dfs(int u){
int m=v.size();
if(u==n) return m>=3;
int max=num[u]=='0'?u+1:n;
vector<int> cur;
for(int i=u;i<max;i++){
cur.insert(cur.begin(),num[i]-'0');
if(m<2||check(v[m-2],v[m-1],cur)){
v.push_back(cur);
if(dfs(i+1)) return true;
v.pop_back();
}
}
return false;
}
bool check(vector<int>& a,vector<int>& b,vector<int>& c){
vector<int> ans;
int cur=0;
for(int i=0;i<a.size()||i<b.size()||cur;i++){
if(i<a.size()) cur+=a[i];
if(i<b.size()) cur+=b[i];
ans.push_back(cur%10);
cur/=10;
}
if(ans.size()!=c.size()) return false;
for(int i=0;i<ans.size();i++){
if(ans[i]!=c[i]) return false;
}
return true;
}
};
思路二 穷举累加序列第一个数字和第二个数字的所有可能性
后面的数据由第一个和第二个数字决定,那么就枚举第一和第二个数据所有的可能性(需要判断前面是否为0来推断这个数据是否满足要求),进而判断后面的数据是否满足条件。另外,这里是字符串相加,需要写一个字符串相加的函数来判断后面的数相加结果是否与前两个数的和相等。
代码二
class Solution {
public:
bool isAdditiveNumber(string num) {
int n=num.size();
for(int secondStart=1;secondStart<n-1;secondStart++){
if(num[0]=='0' && secondStart!=1)
break;
for(int secondEnd=secondStart;secondEnd<n-1;secondEnd++){
if(num[secondStart]=='0' && secondStart!=secondEnd)
break;
if(valid(num,secondStart,secondEnd))
return true;
}
}
return false;
}
bool valid(string num,int secondStart,int secondEnd){
int n=num.size();
int firstStart=0,firstEnd=secondStart-1;
while(secondEnd<n){
if(secondEnd==n-1) return true;
string third=add(num,firstStart,firstEnd,secondStart,secondEnd);
if(third!=num.substr(secondEnd+1,third.size()))
return false;
firstStart=secondStart;
firstEnd=secondEnd;
secondStart=secondEnd+1;
secondEnd=secondEnd+third.size();
}
return false;
}
string add(string num,int firstStart,int firstEnd,int secondStart,int secondEnd){
string ans;
int cur=0;
while(firstStart<=firstEnd || secondStart<=secondEnd || cur){
if(firstStart<=firstEnd) cur+=num[firstEnd--]-'0';
if(secondStart<=secondEnd) cur+=num[secondEnd--]-'0';
ans.push_back(cur%10+'0');
cur/=10;
}
reverse(ans.begin(),ans.end());
return ans;
}
};