给定一个由正整数组成的数组 nums
。
将数组拆分为 一个或多个 不相连的子数组,如下所示:
- 数组中的每个元素都 只属于一个 子数组,并且
- 每个子数组元素的 最大公约数 严格大于
1
。
返回拆分后可获得的子数组的最小数目。
注意:
- 子数组的 最大公约数 是能将子数组中所有元素整除的最大正整数。
-
子数组 是数组的连续部分。
示例 1:
输入: nums = [12,6,3,14,8] 输出: 2 解释: 我们可以把数组分成子数组:[12,6,3] 和 [14,8]。 - 12、6、3 的最大公约数是 3,严格大于 1。 - 14 和 8 的最大公约数是 2,严格来说大于 1。 可以看出,如果不拆分数组将使最大公约数 = 1。
示例 2:
输入: nums = [4,12,6,14] 输出: 1 解释: 我们可以将数组拆分为一个子数组,即整个数组。
提示:
1 <= nums.length <= 2000
2 <= nums[i] <= 109
方法一:贪心 + 数学
对于数组中的每个元素,如果它与前面的元素的最大公约数为
因此,我们先初始化一个变量
接下来,我们从前往后遍历数组,维护当前子数组的最大公约数
时间复杂度
class Solution:
def minimumSplits(self, nums: List[int]) -> int:
ans, g = 1, 0
for x in nums:
g = gcd(g, x)
if g == 1:
ans += 1
g = x
return ans
class Solution {
public int minimumSplits(int[] nums) {
int ans = 1, g = 0;
for (int x : nums) {
g = gcd(g, x);
if (g == 1) {
++ans;
g = x;
}
}
return ans;
}
private int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
}
class Solution {
public:
int minimumSplits(vector<int>& nums) {
int ans = 1, g = 0;
for (int x : nums) {
g = gcd(g, x);
if (g == 1) {
++ans;
g = x;
}
}
return ans;
}
};
func minimumSplits(nums []int) int {
ans, g := 1, 0
for _, x := range nums {
g = gcd(g, x)
if g == 1 {
ans++
g = x
}
}
return ans
}
func gcd(a, b int) int {
if b == 0 {
return a
}
return gcd(b, a%b)
}
function minimumSplits(nums: number[]): number {
let ans = 1;
let g = 0;
for (const x of nums) {
g = gcd(g, x);
if (g == 1) {
++ans;
g = x;
}
}
return ans;
}
function gcd(a: number, b: number): number {
return b ? gcd(b, a % b) : a;
}