今天在leetcode遇到一道很有意思的题。
累加数是一个字符串,组成它的数字可以形成累加序列。
一个有效的累加序列必须至少包含 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
好嘛,第一想法,为了给这个序列“起个头”,不用二重循环是不行了。
因为总要依次地确定第一个数,第二个数的值,否则无法产生相应的序列。
因为我用的是python,所以采取了直接解析数字的方法。
以下便是主体部分:
for i in range(1,len(num)//2+1):
a=int(num[:i])
j=1
while j+i<(len(num)+i)//2+1:
b=int(num[i:i+j])
if junge(a,b,num):
return True
j+=1
这个边界部分是来源于一个数字的基本性质:如果一个数字大于a另一个数字b,那么a的位数至少与b一样,或者多于b。
所以啊,假如我的边界值获得为a=1,b=123,那么余下的58必然不是累加序列里的一个(来源示例1)。
现在主要是junge函数了,我们要由第一二个数字来判断这整个序列的关系。
我写的是这样:(一会讲解)
def junge(a,b,s):
c=a+b
temp=str(a)+str(b)+str(c)
if s==temp:
return True
elif len(s)<len(temp):
return False
if s[:len(temp)]==temp:
return junge(b,c,s[len(str(a)):])
else:
return False
采用了递归的手法,首先我们获得a,b,a+b的这个小序列,如果恰好字符串相等了,是正确的,如果比num还长,那一定是num后面的数字不够用了,那么false。
第二个if语句:比较同长度的一段,并且实际上每次我们把s都“截掉”已经比较完毕的段。所以如果这段如果一样了,那么比较由b,c为起始的序列段,即类似斐波尼茨序列那种。
综合来看,实际上python传递的是引用,所以分割字符串的代价很小,否则这么来回切割,必然不能AC。
下面是完整AC代码:
class Solution:
def isAdditiveNumber(self, num):
"""
:type num: str
:rtype: bool
"""
def junge(a,b,s):
c=a+b
temp=str(a)+str(b)+str(c)
if s==temp:
return True
elif len(s)<len(temp):
return False
if s[:len(temp)]==temp:
return junge(b,c,s[len(str(a)):])
else:
return False
for i in range(1,len(num)//2+1):
a=int(num[:i])
j=1
while j+i<(len(num)+i)//2+1:
b=int(num[i:i+j])
if junge(a,b,num):
return True
j+=1
return False