法一(DFS + 剪枝)
/**
* 在dfs过程中对字符串进行拆分,判断是否满足题意
*
* @param num
* @param index 当前数的下标
* @param cnt 生成数的个数
* @param pre 前一个数的值
* @param sum 前两个数的和
* @return
*/
private boolean dfs(String num, int index, int cnt, long pre, long sum) {
if (index >= num.length()) {
return cnt >= 3; // 生成的数必须要有三个
}
long cur = 0; // 当前拆分的数,为防止溢出,故用long
for (int i = index; i < num.length(); i++) {
if (num.charAt(index) == '0' && i != index) { // 如果有前导0,直接break
break;
}
cur = cur * 10 + num.charAt(i) - '0'; // 计算当前拆分的数
if (cnt >= 2) { // 如果前面已经存在合法的两个数,则判断当前数是否为前两个数的和
if (cur < sum) { // 当前数比前两个数小,继续往后拼接
continue;
}
if (cur > sum) { // 当前数比前两个数大,直接break
break;
}
}
if (dfs(num, i + 1, cnt + 1, cur, pre + cur)) { // 当前数是前两个数的和,则继续向下递归
return true;
}
}
return false;
}
/**
* 法一(DFS + 剪枝)
* 1. DFS
* (1)对字符串进行拆分,遍历所有可能,从第三个数开始,需要判断拆分出的数是否等于前两个数的和
* (2)相等则进行拆分,再继续寻找下一个数,否则不进行拆分,继续循环拼接构成新的数字
* 2. 剪枝
* (1)拆分过程中要保证不能出现前导0,否则直接剪枝
* (2)若第三个数字的和大于前两个数字和,直接剪枝,因为往后只会越来越大
*
* @param num
* @return
*/
public boolean isAdditiveNumber(String num) {
return dfs(num, 0, 0, 0, 0);
}
本地测试
/**
* 306. 累加数
*/
lay.showTitle(306);
Solution306 sol306 = new Solution306();
String num306 = "199100199";
System.out.println(num306 + " " + sol306.isAdditiveNumber(num306));