Medium
题目描述
给你一个二进制数组 nums。
你可以对数组执行以下操作任意次数(可能为零):
- 选择数组中的任意下标
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 <= 10^50 <= nums[i] <= 1
解题思路
解题思路
这道题的关键在于理解翻转操作的本质和最优策略。
核心观察:
- 每次操作会翻转从某个位置到数组末尾的所有元素
- 我们的目标是让所有元素都变成 1
- 从左到右遍历时,如果当前位置是 0,我们必须在这个位置执行翻转操作
贪心策略:
从左到右遍历数组,维护一个变量 operations 记录当前已执行的翻转操作次数。对于每个位置 i:
- 如果
operations是偶数,说明当前位置的值没有被改变,仍是原来的值 - 如果
operations是奇数,说明当前位置的值被翻转了 - 计算当前位置的实际值:
(nums[i] + operations) % 2 - 如果实际值是 0,说明需要在这个位置执行翻转操作,
operations++
正确性证明:
- 要使
nums[0]变成 1,唯一的方法就是在位置 0 执行翻转(如果它原本是 0) - 对于后续位置,如果当前值是 0,我们必须在这个位置翻转,因为这是影响这个位置的最后机会
- 这种贪心策略保证了操作次数最少
推荐解法: 贪心算法,时间复杂度 O(n),空间复杂度 O(1)
代码实现
class Solution {
public:
int minOperations(vector<int>& nums) {
int operations = 0;
for (int i = 0; i < nums.size(); i++) {
// 计算当前位置经过翻转后的实际值
int current = (nums[i] + operations) % 2;
// 如果当前值是0,需要翻转
if (current == 0) {
operations++;
}
}
return operations;
}
};
class Solution:
def minOperations(self, nums: List[int]) -> int:
operations = 0
for i in range(len(nums)):
# 计算当前位置经过翻转后的实际值
current = (nums[i] + operations) % 2
# 如果当前值是0,需要翻转
if current == 0:
operations += 1
return operations
public class Solution {
public int MinOperations(int[] nums) {
int operations = 0;
for (int i = 0; i < nums.Length; i++) {
// 计算当前位置经过翻转后的实际值
int current = (nums[i] + operations) % 2;
// 如果当前值是0,需要翻转
if (current == 0) {
operations++;
}
}
return operations;
}
}
/**
* @param {number[]} nums
* @return {number}
*/
var minOperations = function(nums) {
let operations = 0;
let flipped = false;
for (let i = 0; i < nums.length; i++) {
let currentValue = flipped ? 1 - nums[i] : nums[i];
if (currentValue === 0) {
operations++;
flipped = !flipped;
}
}
return operations;
};
复杂度分析
| 复杂度类型 | 复杂度 | 说明 |
|---|---|---|
| 时间复杂度 | O(n) | 需要遍历整个数组一次 |
| 空间复杂度 | O(1) | 只使用常数额外空间 |
相关题目
- . Minimum Suffix Flips (Medium)