累加数 是一个字符串,组成它的数字可以形成累加序列。
一个有效的 累加序列 必须 至少 包含 3 个数。除了最开始的两个数以外,字符串中的其他数都等于它之前两个数相加的和。
给你一个只包含数字 ‘0’-‘9’ 的字符串,编写一个算法来判断给定输入是否是 累加数 。如果是,返回 true ;否则,返回 false。
说明:累加序列里的数 不会 以 0 开头,所以不会出现 1, 2, 03 或者 1, 02, 3 的情况。
思路
- 字符串的累加 :对两个字符串相加,从末位开始计算,若产生进位,记录在carry里。若某一个字符串已进到首位,则用0代替,直到遍历所有字符串的位且carry=0。
- 判断累加数 :
① 排除以0开头且不是0的数。(如01)
② 判断两数相加的字符长度是否超过剩下的字符长度。
③ 判断两数相加的字符与剩下字符是否相等。
代码实现
- 字符串的累加
string my_add(string& a, string& b)
{
int num1=a.size()-1;
int num2=b.size()-1;
int carry=0;
string ans;
while(num1>=0||num2>=0||carry>0)
{
//若其中一个字符串已完成遍历,则其余位数记为0
int t1=num1>=0?a[num1--]-'0':0;
int t2=num2>=0?b[num2--]-'0':0;
//取相加末位
ans+=(t1+t2+carry)%10+'0';
//若有进位,则记录于carry中
carry=(t1+t2+carry)/10;
}
//反转结果
reverse(ans.begin(),ans.end());
return ans;
}
- 判断累加数
//num表示字符,i表示第一个数的起始下标,j表示第二个数的其实下标,k表示第二个数的末位下标。
bool isvalid(string & num, int i, int j, int k)
{
//排除以0开头且不是0的数。
if(num[i]=='0'&&j!=i+1)return false;
if(num[j]=='0'&&k!=j+1)return false;
string num1=num.substr(i,j-i);
string num2=num.substr(j,k-j);
if(num1.size()==0 || num2.size()==0) return false;
string sum=my_add(num1,num2);
//判断两数相加的字符长度是否超过剩下的字符长度
if(sum.size()+k>num.size()) return false;
//判断两数相加的字符与剩下字符是否相等
for(int s=0;s<sum.size();s++)
{
if(sum[s]!=num[s+k]) return false;
}
if(sum.size()+k==num.size()) return true;
//若还有剩余字符,则将第二个数赋予第一个数,将相加得到的第三个数赋予第二个数
return isvalid(num,j,k,k+sum.size());
}
- 主函数
bool isAdditiveNumber(string num) {
//若累加数的前两个数和字符长度确定,整个数列被确定。
//遍历所有可能的前两个数,判断字符串是否符合累加数标准。
for(int i=0;i<num.size();i++)
{
for(int j=i+1;j<num.size();j++)
{
if (isvalid(num,0,i,j)) return true;
}
}
return false;
}