一、Problem
累加数是一个字符串,组成它的数字可以形成累加序列
一个有效的累加序列必须至少包含 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
进阶: 你如何处理一个溢出的过大的整数输入?
二、Solution
方法一:回溯
思考
获取到当前数 cur 时,如何能检查到前两个数?我选择用一个列表 fab 来存,下面就看看这个原创解法吧…
注:当字符串较长的时候,两个数相加的时候可能会溢出,故用 long 代替 int
class Solution {
public:
vector<long> fab;
bool dfs(int i, string& num) {
if (i==num.size())
return fab.size() > 2;
for (int j=i; j<num.size(); j++) {
string now_s = num.substr(i, j-i+1);
if (now_s .size() > 1 && now_s.find("0") == 0)
continue;
long now = atol(now_s.c_str()), sz = fab.size();
if (fab.size() >= 2 && now != fab[sz-1] + fab[sz-2])
continue;
fab.emplace_back(now);
if (dfs(j+1, num))
return true;
fab.pop_back();
}
return false;
}
bool isAdditiveNumber(string& num) {
return dfs(0, num);
}
};
空间上可优化的地方就是:
- 用一个 last 变量来存储上一个数字,以及用一个 cnt 来代替 fab.size() 的工作
- 还有我们还差一个数 last_last,通过做差法来得到,详细看代码…
class Solution {
public:
bool dfs(int i, long last, long s, int c, string& num) {
if (i==num.size())
return c > 2;
for (int j=i; j<num.size(); j++) {
string next = num.substr(i, j-i+1);
if (next.size() > 1 && next.find("0") == 0)
continue;
long now = atol(next.c_str());
if (c>=2 && now != s)
continue;
if (dfs(j+1, now, last+now, c+1, num))
return true;
}
return false;
}
bool isAdditiveNumber(string& num) {
return dfs(0, 0, 0, 0, num);
}
};
复杂度分析
- 时间复杂度: O ( . . . ) O(...) O(...),
- 空间复杂度: O ( . . . ) O(...) O(...),
方法二:进阶
思考
进阶:当输入的字符串非常长时,写过代码的人都能想到不能强转整形来进行加减,所以很快就能想到用字符串加法以及字符串的比较来实现
所以,进阶问题的破解的核心就变成了字符串 num 的子串的获取(也就是子串下标的选择)
思路
- 我们设三个子串的下标分别为 i、j、k
- 首先,我们从小问题出发,选取的第一个子串的开始下标 i 肯定是 0,且 j > i,k > j
- 有了 i、j、k 我们可以得到三个子串
- 具体的合法判断逻辑 参考代码…
class Solution {
public:
string sum(string& A, string& B) {
int n=A.size(), m=B.size(), i=n-1, j=m-1, ca=0;
string ans;
while (i>=0 || j>=0) {
int a = i<0 ? 0 : A[i--]-'0';
int b = j<0 ? 0 : B[j--]-'0';
int s = a+b+ca, t=0;
if (s >= 10) {
t=s%10;
ca=s/10;
} else {
t=s;
ca=0;
};
ans = to_string(t) + ans;
}
if (ca) ans = to_string(ca) + ans;
return ans;
}
int n;
bool dfs(int i, int j, int k, string& s) {
if (s[i]=='0' && j-i>1 || (s[j]=='0' && k-j>1)) return false;
string a=s.substr(i, j-i), b=s.substr(j, k-j), c=sum(a, b);
int sz=c.size();
if (c != s.substr(k, sz)) return false;
if (sz == n-k) return true;
return dfs(j, k, k+sz, s);
}
bool isAdditiveNumber(string& num) {
n=num.size(); int i=0;
for (int j=i+1; j<=n/2; j++)
for (int k=j+1; k<n; k++) if (dfs(i, j, k, num))
return true;
return false;
}
};
复杂度分析
- 时间复杂度: O ( . . . ) O(...) O(...),
- 空间复杂度: O ( . . . ) O(...) O(...),