解法
看得出来是搜索或者dp,但是没有头绪
中心思想是枚举前两个数,也就是分别枚举它们的长度
肯定要剪枝,怎么剪要自己分析
注意:第二个数可以比第一个数要短
-
假设整个字符串长为 n n n,第一个数长为 i i i,序列至少有3个数,第二个数至少长为1,它们的和至少长为 i i i,所以有: 2 i + 1 ≤ n ⇒ i ≤ ⌊ ( n − 1 ) / 2 ⌋ 2i+1\le n\Rightarrow i\le\lfloor (n-1)/2\rfloor 2i+1≤n⇒i≤⌊(n−1)/2⌋
-
现在第一个数的长度确定为i了,如何确定第2个数的长度呢?我们假设第二个数长为 j j j,第三个数为前两个数的和,所以至少长 max ( i , j ) \max(i,j) max(i,j),因此有: i + j + max ( i , j ) ≤ n i+j+\max(i,j)\le n i+j+max(i,j)≤n
-
假设 j > i j>i j>i,则需要满足: i < j ≤ ( n − i ) / 2 ⇒ 3 i < n i<j\le (n-i)/2 \Rightarrow 3i<n i<j≤(n−i)/2⇒3i<n。也就是说,只有 3 i < n 3i<n 3i<n时,j才可能大于i,并且此时最大值为 ⌊ ( n − i ) / 2 ⌋ \lfloor (n-i)/2\rfloor ⌊(n−i)/2⌋。
-
所以j的长度,在 3 i < n 3i<n 3i<n时可以是 [ 1 , ⌊ ( n − i ) / 2 ⌋ ] [1, \lfloor (n-i)/2\rfloor] [1,⌊(n−i)/2⌋];在 3 i > = n 3i>=n 3i>=n时为 [ 0 , i ] [0,i] [0,i]。
-
特殊情况: 由于数字不能有前导0,所以假如第一个数字或第二个数字的首字符为0,它们长度只能为1
-
特殊情况: 当字符串长小于3时,由于一定不满足3个元素的条件,所以一定不是累加序列。
class Solution(object):
def isAdditiveNumber(self, num):
"""
:type num: str
:rtype: bool
"""
n = len(num)
if n<3:
return False
first_max = (n-1)/2 if num[0]!='0' else 1
def isvalid(i, first, second):
if i>=n:
return True
string = str(first+second)
if num[i:].startswith(string):
return isvalid(i+len(string), second, first+second)
return False
for i in xrange(1,first_max+1):
if num[i]=='0':
second_max = 1
elif 3*i>=n:
second_max = i
else:
second_max = (n-i)>>1
for j in xrange(i+1, i+second_max+1):
first = int(num[:i])
second = int(num[i:j])
if isvalid(j,first,second):
return True
return False