1、题目累加数
累加数 是一个字符串,组成它的数字可以形成累加序列。
一个有效的 累加序列 必须 至少 包含 3 个数。除了最开始的两个数以外,字符串中的其他数都等于它之前两个数相加的和。
给你一个只包含数字 ‘0’-‘9’ 的字符串,编写一个算法来判断给定输入是否是 累加数 。如果是,返回 true ;否则,返回 false 。
说明:累加序列里的数 不会 以 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
提示:
1 <= num.length <= 35
num 仅由数字(0 - 9)组成
进阶:你计划如何处理由过大的整数输入导致的溢出?
2、分析
主要的问题有两个
- 如何选取第一和第二个数字,我用枚举的方式,枚举所有的第一个数和第二个数的选择。只要确定了这两个数字,就可以判断这个选择下是不是累加序列,遍历所有的枚举,就可以确定这个数列能否构成累加序列。
- 可以看到num的长度达到了35,那么我们这里考虑一下进阶的问题,如何处理由过大的整数输入导致的溢出。我打算用字符串存储数值,重写一个字符串的加法。参考
3、代码
class Solution {
public:
bool isAdditiveNumber(string num) {
//长度不足,直接false
if(num.size() < 3) return false;
bool ans = false;
for(int i = 1; i <= num.length() - 2; i ++)
{
for(int j = 1; i + j <= num.length() - 1; j ++)
{
//对于每种前两个数的情况,都进行处理
string first = num.substr(0,i);
string second = num.substr(i,j);
ans = check(first,second,num.substr(i + j));
if(ans) return true;
}
}
return ans;
}
bool check(string a, string b, string other)
{
// 有前导0而不是0的不可以,因为累加序列不能存在带前导0的数
if(a[0] == '0' && a != "0"|| b[0] == '0' && b != "0") return false;
while(other.size())
{
// 使用字符串模拟整数加法
string sum = add(a,b);
// 看看去掉前两位后面的字符串是够以sum开头
if(other.substr(0,sum.size()) != sum) return false;
else{
//是的话更新前两个数以及剩下的字符串
a = b;
b = sum;
other = other.substr(sum.size());
}
}
return true;
}
string add(string a, string b)
{
int t = 0;
//先reverse 方便进位计算
reverse(a.begin(),a.end());
reverse(b.begin(),b.end());
string ans = "";
for(int i = 0; i < a.size() || i < b.size() || t != 0; i ++)
{
if(i < a.size()) t += (a[i] - '0');
if(i < b.size()) t += (b[i] - '0');
ans.push_back(t % 10 + '0');
t /= 10;
}
// reverse之后返回正常的顺序
reverse(ans.begin(),ans.end());
return ans;
}
};
4、总结
参考资料
https://leetcode-cn.com/problems/additive-number