题目
- 恢复数组
- 某个程序本来应该输出一个整数数组。但是这个程序忘记输出空格了以致输出了一个数字字符串,我们所知道的信息只有:数组中所有整数都在 [1, k] 之间,且数组中的数字都没有前导 0 。
给你字符串 s 和整数 k 。可能会有多种不同的数组恢复结果。
按照上述程序,请你返回所有可能输出字符串 s 的数组方案数。
由于数组方案数可能会很大,请你返回它对 10^9 + 7 取余 后的结果。
示例 1:
输入:s = “1000”, k = 10000
输出:1
解释:唯一一种可能的数组方案是 [1000]
示例 2:
输入:s = “1000”, k = 10
输出:0
解释:不存在任何数组方案满足所有整数都 >= 1 且 <= 10 同时输出结果为 s 。
示例 3:
输入:s = “1317”, k = 2000
输出:8
解释:可行的数组方案为 [1317],[131,7],[13,17],[1,317],[13,1,7],[1,31,7],[1,3,17],[1,3,1,7]
示例 4:
输入:s = “2020”, k = 30
输出:1
解释:唯一可能的数组方案是 [20,20] 。 [2020] 不是可行的数组方案,原因是 2020 > 30 。 [2,020] 也不是可行的数组方案,因为 020 含有前导 0 。
示例 5:
输入:s = “1234567890”, k = 90
输出:34
解析
分三个方面分析
一、先考虑不含0,且k足够大的情况
s = “1317”, k = 2000 为例
字符串从1开始下标。
i = 0 时,对应s = ”“,可以解析成空数组 所以dp[0] = 1
i = 1 时,对应s = ”1“,只能解析成 [1], 所以 dp[1] = 1
i = 2 时,对应s = ”13“,只能解析成 [1, 3] 和 [13], 所以 dp[2] = 2
这里,”3“作为数字3加入时,2接在dp[1]构成的所有数组后面,对应的是dp[1], "3"作为数字13加入时,13接在dp[0]构成的所有数组后面,对应时dp[0],所以有转移方程 dp[2] = dp[1] + dp[0]
i = 3 时,对应s = ”131“,dp[3] = 4,dp[3] = dp[2] + dp[1] + dp[0]
i = 4 时,对应s = ”1317“,dp[4] = 8,dp[4] = dp[3] + dp[2] + dp[1] + dp[0]
二、考虑不含0,但是k有限的情况
s = “1317”, k = 20 为例
i = 0 时,对应s = ”“,可以解析成空数组 所以dp[0] = 1
i = 1 时,对应s = ”1“,只能解析成 [1], 所以 dp[1] = 1
i = 2 时,对应s = ”13“,只能解析成 [1, 3] 和 [13], 所以 dp[2] = dp[1] + dp[0] = 2
i = 3 时,对应s = ”131“,”3“只能作为数字3加入,所以dp[3] = dp[2] = 2
i = 4 时,对应s = ”1317“,dp[4] = 4,dp[4] = dp[3] + dp[2] = 4
三、考虑含0,但是k有限的情况
s = “1310”, k = 400 为例
i = 0 时,对应s = ”“,可以解析成空数组 所以dp[0] = 1
i = 1 时,对应s = ”1“,只能解析成 [1], 所以 dp[1] = 1
i = 2 时,对应s = ”13“,只能解析成 [1, 3] 和 [13], 所以 dp[2] = dp[1] + dp[0] = 2
i = 3 时,对应s = ”131“,”1“能作为数字1,31,131加入,所以dp[3] = dp[2] + dp[1] + dp[0] = 4
i = 4 时,对应s = ”1310“,”0“可以作为数字10加入,也可以作为数字310加入,所以dp[4] = dp[2] + dp[1] = 3
这是最复杂的一种情况,可以拆解开来看,
(1)首先,0不能构成数组,0只能与其前面的非0数字构成数字
if s[j] == “0”: continue
(2)0可以作为多少种数字加入,取决于其前面的非0数字大小,例如上面的10, 310.但是如果是”1510“,那就只能以10加入
(3)有一点优化,如果当前字符是0,且与前面的第一个非0字符构成的数字大于k,那么说明往后不能再构成数字了,直接返回0
if s[i - 1] == “0” and dp[i] == 0: return 0
代码
class Solution:
def numberOfArrays(self, s: str, k: int) -> int:
n=len(s)
dp=[0]*(n+1)
dp[0]=1
mod=1000000007
for i in range(1,n+1):
for j in range(i-1,-1,-1):
if s[j]=='0':
continue
if int(s[j:i])<=k:
dp[i]+=dp[j]
else:
if s[i-1]=='0' and dp[i]==0:
return 0
break
dp[i]%=mod
return dp[-1]%mod
运行结果
声明
解析是借鉴大佬的,这只是练习使用,不做商业用途