1. 问题描述:
累加数是一个字符串,组成它的数字可以形成累加序列。一个有效的累加序列必须至少包含 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
进阶:
你如何处理一个溢出的过大的整数输入?
说明: 累加序列里的数不会以 0 开头,所以不会出现 1, 2, 03 或者 1, 02, 3 的情况。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/additive-number
2. 思路分析:
分析题目可以知道我们可以使用三个int类型的变量a, b, c固定两个加数对应的字符串位置,其中num[a + 1:b]表示第一个加数,num[b + 1: c]为第二个加数,使用两层循环就可以表示变量b和c的位置,a一开始的时候为-1这样可以表示从0开始截取的若干个位置对应的数字为第一个加数,所以使用两层循环即可表示两个加数。因为需要去除掉前导0,所以第一个加数与第二个加数是不能够存在前导0的,判断第一个加数是否存在前导0:b - a > 1 and num[a + 1] == "0" 说明第一个加数位数大于1且第一位是0所以存在前导0,对于第二个加数也是类似的,c -b > 1 and num[b + 1] == "0"说明第二个加数存在前导0。因为使用的是python语言所以使用字符串的切片操作截取字符串得到对应的两个加数x, y,然后使用高精度加法计算两个字符串对应的数字相加的结果(高精度加法使用数组或者列表来存储两个加数对应位置上的数字然后模拟两个数字相加的过程最后返回字符串结果),然后判断相加的结果是否等于num中截取的字符串对应的结果,如果相等那么移动a, b, c的位置进行下一个两个加数相加的操作,否则break,最后判断一下c + 1是否等于num的长度,如果相等说明是一个有效的累加序列。
3. 代码如下:
class Solution:
# 高精度加法
def add(self, a: str, b: str):
A, B, C = list(), list(), list()
# 逆序遍历的目的是为了得到从低位开始的数字这样方便相加的时候从低位开始相加
for i in range(len(a) - 1, -1, -1):
A.append(int(a[i]))
for i in range(len(b) - 1, -1, -1):
B.append(int(b[i]))
i, t = 0, 0
while i < len(A) or i < len(B) or t:
if i < len(A): t += A[i]
if i < len(B): t += B[i]
C.append(t % 10)
t //= 10
i += 1
z = ""
for i in range(len(C) - 1, -1, -1):
z += str(C[i])
return z
def isAdditiveNumber(self, num: str) -> bool:
for i in range(len(num)):
for j in range(i + 1, len(num)):
a = -1
b = i
c = j
while True:
# 判断第一个加数是否存在前导0
if b - a > 1 and num[a + 1] == "0": break
# 判断第二个加数是否存在前导0
if c - b > 1 and num[b + 1] == "0": break
# 第一个加数
x = num[a + 1:a + 1 + b - a]
# 第二个加数
y = num[b + 1:b + 1 + c - b]
z = self.add(x, y)
if num[c + 1:c + 1 + len(z)] != z: break
# 移动a,b,c的位置
a = b
b = c
c = c + len(z)
if c + 1 == len(num): return True
return False