306. Additive Number

解法

看得出来是搜索或者dp,但是没有头绪

参考:https://blog.csdn.net/x_i_y_u_e/article/details/50724390

中心思想是枚举前两个数,也就是分别枚举它们的长度
肯定要剪枝,怎么剪要自己分析
注意:第二个数可以比第一个数要短

  1. 假设整个字符串长为 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+1ni(n1)/2

  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

  3. 假设 j &gt; i j&gt;i j>i,则需要满足: i &lt; j ≤ ( n − i ) / 2 ⇒ 3 i &lt; n i&lt;j\le (n-i)/2 \Rightarrow 3i&lt;n i<j(ni)/23i<n。也就是说,只有 3 i &lt; n 3i&lt;n 3i<n,j才可能大于i,并且此时最大值为 ⌊ ( n − i ) / 2 ⌋ \lfloor (n-i)/2\rfloor (ni)/2

  4. 所以j的长度,在 3 i &lt; n 3i&lt;n 3i<n时可以是 [ 1 , ⌊ ( n − i ) / 2 ⌋ ] [1, \lfloor (n-i)/2\rfloor] [1,(ni)/2];在 3 i &gt; = n 3i&gt;=n 3i>=n时为 [ 0 , i ] [0,i] [0,i]

  5. 特殊情况: 由于数字不能有前导0,所以假如第一个数字或第二个数字的首字符为0,它们长度只能为1

  6. 特殊情况: 当字符串长小于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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值