1416. 恢复数组
大约 2 分钟
---
1416. 恢复数组
- 标签:字符串、动态规划
- 难度:困难
题目链接
题目大意
描述:给定一个字符串 和一个整数 。将 分割成若干非空子串,每个子串表示的整数在 范围内,且没有前导零。
要求:返回分割方案数。结果对 取模。
说明:
- 。
- 。
示例:
- 示例 1:
输入:s = "1000", k = 10000
输出:1
解释:唯一一种可能的数组方案是 [1000]- 示例 2:
输入:s = "1000", k = 10
输出:0
解释:不存在任何数组方案满足所有整数都 >= 1 且 <= 10 同时输出结果为 s 。解题思路
思路 1:DP
1. 核心思想
定义 表示前 个字符()的分割方案数。
转移:枚举最后一个子串的起点 (从 向前), 形成的整数 ,且无前导零。。
2. 具体步骤
第 1 步:初始化 。
第 2 步:遍历 :
- 从 开始向前枚举 ,如果 (前导零),跳过。
- 截取 。
- 如果 ,由于 长度很大但 有限,且数字增长很快,可以提前终止(因为子串长度超过 位数时一定 )。
- 否则 。
第 3 步:返回 。
3. 复杂度优化
,其十进制位数最多 位。所以 只需要向前枚举最多 位即可。因此时间 。
4. 举例说明
以 为例:
- :,,。
- :(前导零),跳过。,,。
- :,跳过。,前导零。,,。
- :,跳过。,跳过。,前导零。,,。
结果:(只有一种分法:"1000")。
思路 1:代码
class Solution:
def numberOfArrays(self, s: str, k: int) -> int:
MOD = 10**9 + 7
n = len(s)
dp = [0] * (n + 1)
dp[0] = 1
max_len = len(str(k)) # k 的十进制位数
for i in range(1, n + 1):
# 最多检查 max_len 位
for j in range(max(0, i - max_len), i):
if s[j] == '0':
continue
num = int(s[j:i])
if num > k:
continue
dp[i] = (dp[i] + dp[j]) % MOD
return dp[n]思路 1:复杂度分析
- 时间复杂度:,,,相当于 。
- 空间复杂度:,DP 数组。