切分数组
难度:
标签:
题目描述
English description is not available for the problem. Please switch to Chinese.
代码结果
运行时间: 361 ms, 内存: 38.0 MB
/*
题目思路:
1. 使用Java Stream API遍历数组并找到每个可能的切割点,计算其前后子数组的最大公约数。
2. 如果某个切割点的前后子数组的头尾最大公约数都大于1,则可以切割。
3. 记录最少的切割次数。
*/
import java.util.stream.IntStream;
public class Solution {
// 计算两个数的最大公约数
private int gcd(int a, int b) {
if (b == 0) return a;
return gcd(b, a % b);
}
public int minCuts(int[] nums) {
int n = nums.length;
int[] cuts = {0};
IntStream.range(0, n).forEach(i -> {
if (i > 0 && gcd(nums[i - 1], nums[i]) == 1) {
cuts[0]++;
}
});
return cuts[0] + 1;
}
}
解释
方法:
本题解采用动态规划的思想以及预处理的方法来解决问题。首先,通过一个预处理步骤,使用筛法计算每个数字的最小质因子。这个预处理步骤是基于一个修改版的埃拉托斯特尼筛法,只针对较小的质数。对于数组中的每个数字,我们使用预处理的结果来快速找到它的所有质因子,并且通过动态规划的方式计算如何分割数组以满足题目要求。动态规划的状态 f[p] 表示最后一个使用质数 p 作为头尾最大公约数的子数组所形成的最小切割数。对于每个数字 x,我们更新它的所有质因子对应的状态,然后找出最小的切割数作为当前位置的结果,并不断向前推进。
时间复杂度:
O(n log x)
空间复杂度:
O(M)
代码细节讲解
🦆
在题解中提到的埃拉托斯特尼筛法是如何被修改的?具体修改了哪些部分?
▷🦆
题解中使用了动态规划,具体的状态定义是什么?状态转移方程是如何根据题目要求构建的?
▷🦆
为什么题解选择只计算小于1000的质数?处理大于1000的数时策略有什么不同?
▷