leetcode 2654. 使数组所有元素变成 1 的最少操作次数 中等
给你一个下标从 0 开始的 正 整数数组 nums 。你可以对数组执行以下操作 任意 次:
- 选择一个满足
0 <= i < n - 1的下标i,将nums[i]或者nums[i+1]两者之一替换成它们的最大公约数。
请你返回使数组 nums 中所有元素都等于 1 的 最少 操作次数。如果无法让数组全部变成 1 ,请你返回 -1 。
两个正整数的最大公约数指的是能整除这两个数的最大正整数。
示例 1:
输入:nums = [2,6,3,4] 输出:4 解释:我们可以执行以下操作: - 选择下标 i = 2 ,将 nums[2] 替换为 gcd(3,4) = 1 ,得到 nums = [2,6,1,4] 。 - 选择下标 i = 1 ,将 nums[1] 替换为 gcd(6,1) = 1 ,得到 nums = [2,1,1,4] 。 - 选择下标 i = 0 ,将 nums[0] 替换为 gcd(2,1) = 1 ,得到 nums = [1,1,1,4] 。 - 选择下标 i = 2 ,将 nums[3] 替换为 gcd(1,4) = 1 ,得到 nums = [1,1,1,1] 。
示例 2:
输入:nums = [2,10,6,14] 输出:-1 解释:无法将所有元素都变成 1 。
提示:
2 <= nums.length <= 501 <= nums[i] <= 10^6
分析:如果 nums 数组中有 1,因为 1 与任何数的最大公约数都是 1,所以此时答案是 nums 数组中不为 1 的数的个数。如果数组中没有 1,则如果存在两个数互素,也可以将 nums 数组都变成 1,此时答案是这两个互素的数之间的距离加上数组长度减1,理由就是先找到最近的两个互素的数,得到一个 1,再用这个 1 把其它所有的数都变成 1。如果数组中不存在两个互素的数,说明不能让数组全部变成 1.
令 temp 代表当前计算得到的最大公约数,它的初值为 nums[0],之后每次让 temp 与 nums[i] 求 gcd,当得到的 gcd 等于 1,从 i 开始,向前计算 gcd,求出这次的两个互素的数的最短距离。遍历完数组,求得这个最短距离,再加上数组长度减 1 就是答案。
int gcd(int a,int b)
{if(a==0)return b;return gcd(b,a%b);
}int minOperations(int* nums, int numsSize) {int ans=-1;for(int i=1;i<numsSize;++i){if(nums[i]==1||nums[i-1]==1)return numsSize-1;if(gcd(nums[i],nums[i-1])==1){int temp=0,ind=i;while(ind>1){if(gcd(nums[ind],nums[ind-1])==1)break;}}}return ans;
}
