累加数 是一个字符串,组成它的数字可以形成累加序列。

一个有效的 累加序列 必须 至少 包含 3 个数。除了最开始的两个数以外,字符串中的其他数都等于它之前两个数相加的和。

给你一个只包含数字 '0'-'9' 的字符串,编写一个算法来判断给定输入是否是 累加数 。如果是,返回 true ;否则,返回 false 。

说明:累加序列里的数,除数字 0 之外,不会 以 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:
输入:"11245157"
输出:true 
解释:累加序列为: 112, 45, 157。112 + 45 = 157

分析:

拿"11245157"举例:

  • 1 + 1 = 2 满足条件,进行下一层
  • 4 + 5 ≠ 1 ≠ 15 ≠ 157 不满足,调整后面加数
  • 4 + 51 ≠ 5 ≠ 57 不满足,调整后面加数
  • 4 + 515 ≠ 7 不满足,后面加数调整完,调整前面加数
  • 45 + 1 ≠ 5 ≠ 57 不满足,调整后面加数
  • 45 + 15 ≠ 7 不满足,后面加数调整完,调整前面加数
  • 451 + 5 ≠ 7 不满足,前面加数调整完,此层无结果,回到上一层
  • 1 + 12 ≠ 4 ≠ 45 ≠ 451 ≠ 4515 ≠ 45157 不满足,调整后面加数
  • ...... 按照上面方式遍历
  • 112 + 45 ≠ 1 ≠ 15 == 157 满足条件,结束

不难看出,这种题用回溯来解比较简单,采取深度优先的遍历,满足条件进行下一层遍历,下一层若所有节点都不满足条件,则回溯到上一层,直到一个分支满足条件或都不满足条件结束。考虑要动态进行添加删除,我们可以用一个集合(List)来存储结果,满足条件时,加入集合,下一层不满足条件时移出集合。需要注意的几点是:

  1. 集合每三个元素为:加数,加数,和。和在与前面加数和相等时加入,然后进入下一层遍历。
  2. 遍历到最后一层时,若集合还是三个以上,说明没有回溯,都满足条件,返回真,否则假。
  3. 如果首数字为 0 ,那么此加数或和只能为 0
class Solution {

    //累加序列单个数
    char[] cs = null;
    //序列长度
    int len = 0;
    //结果集合
    List<Integer> res = new ArrayList<>();

    public boolean isAdditiveNumber(String num) {
        cs = num.toCharArray();
        len = cs.length;
        return dfs(0);
    }

    //深度优先遍历
    public boolean dfs(int n){
        int size = res.size();
        //遍历完了,若集合还是三个以上,说明没有回溯,都满足条件
        if(n == len){
            return size >= 3;
        }
        //如果首数字为 0 ,那么此加数只能为 0
        int length = cs[n] == '0'? n + 1: len;
        //加数或和
        int sum = 0;
        //遍历
        for(int i = n; i < length; ++i){
            //累加
            sum = sum * 10 + cs[i] - '0';
            //集合长度不小于2时进行加法比较
            if(size < 2 || res.get(size - 2) + res.get(size-1) == sum){
                //添加加数或和
                res.add(sum);
                //进行下一层比较
                if(dfs(i+1)){
                    return true;
                }
                //下一层节点都不满足,删除添加的数,进行回溯
                res.remove(size);
            }
        }
        return false;
    }
}

题目来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/additive-number