题目描述
累加数是一个字符串,组成它的数字可以形成累加序列。
一个有效的累加序列必须至少包含 3 个数。除了最开始的两个数以外,字符串中的其他数都等于它之前两个数相加的和。
给定一个只包含数字 ‘0’-‘9’ 的字符串,编写一个算法来判断给定输入是否是累加数。
说明: 累加序列里的数不会以 0 开头,所以不会出现 1, 2, 03 或者 1, 02, 3 的情况。
样例描述
思路
方法一:字符串模拟 + 高精度加法 O(n^3)
- 枚举第一段的长度,枚举第二段的长度,看和是否匹配第三段的长度。枚举中不能枚举前导0的数。匹配的话不断的移动a,b,c。
- java的substring是表示首尾索引,并且左闭右开。
- 初始让a=-1且每段都初始指向该段前一个数,是类似虚拟头结点的思想,为了让处理第一个数和后面保持一致。
- 高精度加法模板要背过。(记得先转化为stringbuilder逆序,也可以直接从后往前遍历)
方法二:回溯 + 剪枝
- 对字符串进行拆分,遍历所有可能。从第三个数字开始,判断是否满足等于前两个数的和,满足的话就拆分,再继续找下一个数。否则的话继续拼接构成新的数字。防止溢出,拆分的数用long。
- 如果第三个数字的和大于前两个数字和,就没必要继续下去,直接剪枝,因为往后只能越来越大。
- 拆分过程中要保证不能出现前导0,除了0本身以外。如果不是第一位就不能为0,否则直接剪枝。
- 回溯中记录前两个数和,上一个数的值,当前下标以及已经生成的数的个数。
代码
class Solution {
public boolean isAdditiveNumber(String num) {
int n = num.length();
for (int i = 0; i < n; i ++ ) {
//至少三个数,所以让j的一个数也在范围内
for (int j = i + 1; j + 1 < n; j ++ ) {
//指向每一段的前一个数(也就是上一段的最后一个数)
int a = -1, b = i, c = j;
//由于不知道判断多少段和,所以设置不断循环直到末尾或者匹配失败
while (true) {
String s1 = num.substring(a + 1, b + 1);