3191 使二进制数组全部等于 1 的最少操作次数 I
给你一个二进制数组 nums 。
你可以对数组执行以下操作 任意 次(也可以 0 次):
选择数组中 任意连续 3 个元素,并将它们 全部反转 。
反转 一个元素指的是将它的值从 0 变 1 ,或者从 1 变 0 。
请你返回将 nums 中所有元素变为 1 的 最少 操作次数。如果无法全部变成 1 ,返回 -1 。
示例 1:
输入:nums = [0,1,1,1,0,0]
输出:3
解释:
我们可以执行以下操作:
选择下标为 0 ,1 和 2 的元素并反转,得到 nums = [1,0,0,1,0,0] 。
选择下标为 1 ,2 和 3 的元素并反转,得到 nums = [1,1,1,0,0,0] 。
选择下标为 3 ,4 和 5 的元素并反转,得到 nums = [1,1,1,1,1,1] 。
示例 2:
输入:nums = [0,1,1,1]
输出:-1
解释:
无法将所有元素都变为 1 。
提示:
$3 <= nums.length <= 10^5$
$0 <= nums[i] <= 1$
思路:
这个题要求连续三个数反转,所以我们可以直接从头开始计算,
- 如果第一个是
0
,那么说明我们需要反转一次,(也就是第一个,第二个和第三个都需要反转)。 - 如果第一个是
1
,则说明我们不需要操作。
- 然后我们再看二个,与第一个相同,这里要注意我们前面第一个如果是
0
我们是对第二个反转了一遍。之后就是相同的操作。
整体就是按顺序进行模拟。
class Solution {
public:
int minOperations(vector<int>& nums) {
int n=nums.size();
int ans=0;
for(int i=2;i<n;i++){
if(nums[i-2]==0){
nums[i-2]=1;
nums[i-1]^=1;
nums[i]^=1;
ans++;
}
}
if(nums[n-1]==0||nums[n-2]==0) return -1;
return ans;
}
};
进阶版 3192. 使二进制数组全部等于 1 的最少操作次数 II
给你一个二进制数组 nums 。
你可以对数组执行以下操作 任意 次(也可以 0 次):
选择数组中 任意 一个下标 i ,并将从下标 i 开始一直到数组末尾 所有 元素 反转 。
反转 一个元素指的是将它的值从 0 变 1 ,或者从 1 变 0 。
请你返回将 nums 中所有元素变为 1 的 最少 操作次数。
示例 1:
输入:nums = [0,1,1,0,1]
输出:4
解释:
我们可以执行以下操作:
选择下标 i = 1 执行操作,得到 nums = [0,0,0,1,0] 。
选择下标 i = 0 执行操作,得到 nums = [1,1,1,0,1] 。
选择下标 i = 4 执行操作,得到 nums = [1,1,1,0,0] 。
选择下标 i = 3 执行操作,得到 nums = [1,1,1,1,1] 。
示例 2:
输入:nums = [1,0,0,0]
输出:1
解释:
我们可以执行以下操作:
选择下标 i = 1 执行操作,得到 nums = [1,1,1,1] 。
提示:
$1 <= nums.length <= 105$
$0 <= nums[i] <= 1$
思路:
这个题要求i后面都反转,同样的我们可以直接从头开始计算,(模拟):
如果前面i-1
位都已经符合条件,并且需要反转x
次。那么我看来第i
位。
- 如果第
i
位是0
,经过x
次转换后,它应该是y=(0+x)%2
, - 如果第
i
位是1
,经过x
次转换后,它应该是y=(1+x)%2
,
- 如果y是
0
,则说明在第i位上需要反转一次。那么i位后的位置需要反转x+1
次。 - 如果y是
1
,则说明在第i位上就不需要操作了。
整体就是按顺序进行模拟。
class Solution {
public:
int minOperations(vector<int>& nums) {
int n=nums.size();
int ans=0;
int flag=0;
for(int i=0;i<n;i++){
if((nums[i]+flag)%2==0){
flag^=1;
ans++;
}
}
return ans;
}
};