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的模板讲解,这位也是套用了下面的
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/