刷题日记:

leetcode 2719(leetcode给我的每日一题,难度:困难):

给你两个数字字符串 num1 和 num2 ,以及两个整数 max_sum 和 min_sum 。如果一个整数 x 满足以下条件,我们称它是一个好整数:

  • num1 <= x <= num2
  • min_sum <= digit_sum(x) <= max_sum.

请你返回好整数的数目。答案可能很大,请返回答案对 109 + 7 取余后的结果。

注意,digit_sum(x) 表示 x 各位数字之和。

示例 1:

输入:num1 = "1", num2 = "12", min_num = 1, max_num = 8
输出:11
解释:总共有 11 个整数的数位和在 1 到 8 之间,分别是 1,2,3,4,5,6,7,8,10,11 和 12 。所以我们返回 11 。

下面代码:自己写的,虽然示例通过了,但提交的时候有时间限制(数字很大) ,等于白写:

class Solution(object):
    def digit_sum(self,x):
        sum = 0
        while x != 0:
            sum += x % 10
            x //= 10
        return sum
       
    def count(self, num1, num2, min_sum, max_sum):
        """
        :type num1: str
        :type num2: str
        :type min_sum: int
        :type max_sum: int
        :rtype: int
        """
        min_num=int(num1)
        max_num=int(num2)
        i=min_num
        list=[]
        while i>=min_num and i<=max_num:
            if self.digit_sum(i)<=max_sum and self.digit_sum(i)>=min_sum:
                list.append(i)
            i=i+1
        i=len(list)
        return i%((10**9) + 7)

这是评论区‘北理的别卷了’的(比官方的简短) :

关于数位DP的模板讲解,这位也是套用了下面的

. - 力扣(LeetCode)

class Solution:
    def count(self, num1: str, num2: str, min_sum: int, max_sum: int) -> int:
        m = len(num2)
        #将字符串num2中的每个字符转换为整数,并以列表形式存储在up_limit变量中
        up_limit = list(map(int, num2))  
        #字符串num1进行了一个填充操作,使其长度和字符串num2相同。填充使用0来填充空位,这里使用了字符串的zfill方法。然后,将填充后的字符串转换成一个整数列表,存储在down_limit变量中。
        down_limit = list(map(int, num1.zfill(m)))
        mod = 10 ** 9 + 7
        #使用了缓存装饰器@cache来优化计算过程,避免重复计算
        @cache
        def f(i=0, s=0, valid=False, dlimit=True, ulimit=True):
            if i == m:
                return int(valid and min_sum <= s <= max_sum)
            down = down_limit[i] if dlimit else 0
            up = up_limit[i] if ulimit else 9
            ans = 0
            for d in range(down, up + 1):
                ans = (ans + f(i + 1, s + d, valid or d != 0, dlimit and d == down, ulimit and d == up)) % mod
            return ans
        return f()

官方题解:(关于动态规划的问题-----我还没搞懂)

class Solution:
    def count(self, num1: str, num2: str, min_sum: int, max_sum: int) -> int:
        def dfs(num, i, j, limit) -> int:
            if j > max_sum:
                return 0
            if i == -1:
                return j >= min_sum
            if not limit and d[i][j] != -1:
                return d[i][j]
            res = 0
            up = ord(num[i]) - ord('0') if limit > 0 else 9
            for x in range(up + 1):
                res = (res + dfs(num, i - 1, j + x, limit and x == up)) % MOD
            if not limit:
                d[i][j] = res
            return res

        def get(num):
            num = num[::-1]
            return dfs(num, len(num) - 1, 0, True)

        # 求解 num - 1,先把最后一个非 0 字符减去 1,再把后面的 0 字符变为 9
        def sub(num):
            i = len(num) - 1
            arr = list(num)
            while arr[i] == '0':
                i -= 1
            arr[i] = chr(ord(arr[i]) - 1)
            i += 1
            while i < len(num):
                arr[i] = '9'
                i += 1
            return ''.join(arr)

        N, M = 23, 401
        MOD = 10**9 + 7
        d = [[-1] * M for _ in range(N)]
        return (get(num2) - get(sub(num1)) + MOD) % MOD

作者:力扣官方题解
链接:https://leetcode.cn/problems/count-of-integers/solutions/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值