二、字符串(42)306. 累加数

累加数 是一个字符串,组成它的数字可以形成累加序列。

 

一个有效的 累加序列 必须 至少 包含 3 个数。除了最开始的两个数以外,序列中的每个后续数字必须是它之前两个数字之和。

给你一个只包含数字 '0'-'9' 的字符串,编写一个算法来判断给定输入是否是 累加数 。如果是,返回 true ;否则,返回 false 。

说明:累加序列里的数,除数字 0 之外,不会 以 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

提示:

  • 1 <= num.length <= 35
  • num 仅由数字(0 - 9)组成

进阶:你计划如何处理由过大的整数输入导致的溢出?

官方题解:

class Solution:

    def isAdditiveNumber(self, num: str) -> bool:
        n = len(num)#字符串的长度
        #一个有效的 累加序列 必须 至少 包含 3 个数,所以 0 和 n-1 是第二个数不能取到的,要留给前面和后面的数
        #遍历第二个数的可能的开始和结尾的范围
        for secondStart in range(1, n - 1):#第二个数的开始范围
            if num[0] == '0' and secondStart != 1:#累加序列里的数,除数字 0 之外,不会 以 0 开头,num[0] == '0'则secondStart只能为1,其他情况就不用在进行判断
                break
            for secondEnd in range(secondStart, n - 1):#第二个数的结尾范围,从secondStart+1开始遍历
                if num[secondStart] == '0' and secondStart != secondEnd:#如果num[secondStart] == '0',那么第二个数必须为0,第二个数的开始即结尾
                    break
                if self.valid(secondStart, secondEnd, num):#一个累加序列,当它的第一个数字和第二个数字以及总长度确定后,这整个累加序列也就确定了。
                    return True
        return False
    
    #判断累加序列是否有效
    def valid(self, secondStart: int, secondEnd: int, num: str) -> bool:
        n = len(num)#字符串的长度
        firstStart, firstEnd = 0, secondStart - 1#确定第一个数字,得到第二个数字的开始位置就可以求到第一个数字了
        
        while secondEnd <= n - 1:#secondEnd在有效范围内时
            third = self.stringAdd(num, firstStart, firstEnd, secondStart, secondEnd)#第一个数和第二个数相加得到第三个数
            thirdStart = secondEnd + 1#第三个数的起始位置
            thirdEnd = secondEnd + len(third)#第三个数的终止位置

            if thirdEnd >= n or num[thirdStart : thirdEnd + 1] != third:#越界或不等
                break
            if thirdEnd == n - 1:#只有三个数
                return True
            #第二个数的第三个数变成新的第一、二个数
            firstStart, firstEnd = secondStart, secondEnd
            secondStart, secondEnd = thirdStart, thirdEnd

        return False

    #将传入的第一个数和第二个数相加
    def stringAdd(self, s:str, firstStart: int, firstEnd: int, secondStart: int, secondEnd: int) -> str:
        third = []#空列表
        carry, cur = 0, 0#进位,当前值
        
        while firstEnd >= firstStart or secondEnd >= secondStart or carry != 0:#加上第一个和第二个数

            cur = carry#上一次的进位是当前值

            #每次加上两个数的同一位
            if firstEnd >= firstStart:#第一个数成立 123
                cur += ord(s[firstEnd]) - ord('0')#ord将字符转换为整数
                firstEnd -= 1

            if secondEnd >= secondStart:#第二个数成立236
                cur += ord(s[secondEnd]) - ord('0')
                secondEnd -= 1

            carry = cur // 10#进位
            cur %= 10#当前位的值
            third.append(chr(cur + ord('0')))
        return ''.join(third[::-1])#将列表的元素反转并拼接

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值