恢复数组
难度:
标签:
题目描述
代码结果
运行时间: 460 ms, 内存: 20.3 MB
/*
* 思路:
* 使用 Stream 和 lambda 表达式来进行动态规划计算。
*/
import java.util.stream.IntStream;
public class Solution {
public int numberOfArrays(String s, int k) {
int n = s.length();
int mod = 1000000007;
int[] dp = new int[n + 1];
dp[0] = 1;
IntStream.rangeClosed(1, n).forEach(i -> {
long[] num = {0};
IntStream.iterate(i, j -> j - 1).limit(i).forEach(j -> {
num[0] = num[0] + (s.charAt(j - 1) - '0') * (long)Math.pow(10, i - j);
if (num[0] > k) return;
if (s.charAt(j - 1) != '0') {
dp[i] = (dp[i] + dp[j - 1]) % mod;
}
});
});
return dp[n];
}
}
解释
方法:
此题解采用动态规划的方法解决问题。定义 dp[i] 为字符串 s 的前 i 个字符可以形成的有效数组的方案数。初始化 dp[0] = 1,表示空字符串有一种划分方式(即没有数字)。遍历字符串 s 的每一个位置 i,如果当前位置字符为 '0' 或 dp[i] 为 0(表示无法从前面的字符转移至此),则直接跳过该位置。对于每个有效的起点 i,尝试将从位置 i 到 j 的子串转化为数字,并判断是否不超过 k。若不超过 k,则将 dp[i] 的方案数加到 dp[j+1] 上。这样,我们可以通过前面的位置来更新后面的位置的方案数。最终,dp[len(s)] 存储的是整个字符串 s 可以形成的有效数组的总方案数。
时间复杂度:
O(n^2)
空间复杂度:
O(n)
代码细节讲解
🦆
在动态规划数组 dp 中,dp[i] 表示的具体意义是什么?
▷🦆
该算法中为什么要在每次循环开始时检查 dp[i] 是否为0,它的含义是什么?
▷🦆
为什么在算法中需要将数字字符转换成整数列表进行处理,直接使用字符串处理有什么不足?
▷🦆
在内层循环中,num 的构建方式可能会导致整数溢出吗?如果会,如何避免?
▷