直觉
- 本题中,我们发现对同一个位置翻转两次,等同于没有翻转。
- 此外,对某个元素进行翻转的方式只有以下三种:
- 翻转当前元素
- 翻转当前元素的前一个
- 翻转当前元素的前两个
- 这意味着一旦我们越过某个元素,就无法再对它进行翻转。
思路
- 因此,我们可以从左到右遍历数组,对每个值为 0 的元素执行翻转,最后检查整个数组是否全为 1。
- 为什么这个方法是正确的?
首先,我们知道一旦越过某个元素,就无法再翻转它。
这意味着当我们遍历到某个元素时,必须在此处将其翻转为 1。如果跳过这一步,该位置将永远保持 0,不满足题目要求。因此,这一步是必要操作,跳过它将无法得到目标数组。
同样可以证明,对于所有能达到目标状态的数组,这个贪心策略都能给出正确结果——因为无论执行什么操作,当前为 0 的元素都必须在此处被翻转。
复杂度
- 时间复杂度:$O(N)$,N 为数组长度。
- 空间复杂度:$O(1)$。
代码
class Solution:
def minOperations(self, nums: List[int]) -> int:
cnt = 0
for i in range(len(nums) - 2):
if nums[i] == 0:
cnt += 1
nums[i] = 1
nums[i + 1] = 1 - nums[i + 1]
nums[i + 2] = 1 - nums[i + 2]
if nums[-1] == 1 and nums[-2] == 1:
return cnt
return -1