Leetcode 995. K 连续位的最小翻转次数

题目:

在仅包含 0 1 的数组 A 中,一次 K 位翻转包括选择一个长度为 K 的(连续)子数组,同时将子数组中的每个 0 更改为 1,而每个 1 更改为 0

返回所需的 K 位翻转的次数,以便数组没有值为 0 的元素。如果不可能,返回 -1

示例 1

输入:A = [0,1,0], K = 1
输出:2
解释:先翻转 A[0],然后翻转 A[2]
示例 2

输入:A = [1,1,0], K = 2
输出:-1
解释:无论我们怎样翻转大小为 2 的子数组,我们都不能使数组变为 [1,1,1]
示例 3

输入:A = [0,0,0,1,0,1,1,0], K = 3
输出:3
解释:
翻转 A[0],A[1],A[2]: A变成 [1,1,1,1,0,1,1,0]
翻转 A[4],A[5],A[6]: A变成 [1,1,1,1,1,0,0,0]
翻转 A[5],A[6],A[7]: A变成 [1,1,1,1,1,1,1,1]
 

提示:

1 <= A.length <= 30000
1 <= K <= A.length

思路:

参考了官方的题解,但不是很理解,后面尝试着加了一些适合自己脑回路的理解。

整体思路和官方是一样的,我们需要1个变量记录翻转次数是奇数次还是偶数次,还需要长度为n的数组去记载在某个位置需要翻转回来。

下面这个是官方的解释:

作者:LeetCode

链接:https://leetcode-cn.com/problems/two-sum/solution/k-lian-xu-wei-de-zui-xiao-fan-zhuan-ci-shu-by-leet/

来源:力扣(LeetCode

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

每次翻转一个子数组 A[i], A[i+1], ..., A[i+K-1],我们可以考虑这样的两种事件:第一种是 开始事件,标记位置 i 为我们翻转子数组的开始,另一种是 结束事件,标记位置 i+K 是我们翻转子数组的结束。使用这些事件,我们就可以知道某一个位置被多少个重叠的翻转子数组覆盖了:它的数值等于 开始事件的数量减去 结束事件的数量。

当我们翻转子数组形如A[i]...A[i + k - 1],总共k个。

我们可以在此位置置反翻转状态,并且在位置 A[i + k] 设置一个提醒,告诉我们在那里也要置反翻转状态

为什么到A[i + k]时需要翻回来呢?

我们将翻转状态置反,说明了需要翻转的区间为[i, i + k - 1],到了i + k时,翻转状态再一次置反,说明不需要翻转。

接下来是我在官方原代码上加的一些自己的理解。

class Solution {
    public int minKBitFlips(int[] A, int K) {
        int N = A.length;
        int res = 0, fli = 0;
        
        int[] fan = new int[N];
        for(int i = 0; i < N; ++i){
            fli ^= fan[i];       //异或是不进位的加法
            /*  fli(原)  fan[i]  fli(现)
                0         0      0     不需要操作
                0         1      1     这里需要翻的次数要加1,从偶数次变为奇数次
                1         0      1     原先翻过奇数次,现在不用管,还是奇数次
                1         1      0     原先翻过奇数次,现在再翻一次,变为偶数次
            */
            
            if(A[i] == fli){  /*有两种情况:1.fli翻过奇数次,而原A[i]为1,说明还要再翻;
                                          2.fli翻过偶数次,而原A[i]为0,说明还要再翻;*/
                ++res;
                if(i + K > N){
                    return -1;
                }
                fli ^= 1;    //相当于fli = (fli + 1) % 2
                if(i + K < N){
                    fan[i + K] ^= 1; //相当于fan[i + K] = (fan[i + K] + 1) % 2
                }
            }
        }
        return res;
    }
}

时间复杂度(n );

空间复杂度(n );

猜你喜欢

转载自www.cnblogs.com/ledphz/p/11333169.html