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. 1 <= A.length <= 30000
  2. 1 <= K <= A.length

 

首先,对于每个位置,只有初始状态和反转总数确定最终状态。

另一方面,我们知道每个长度为K的间隔最多只能反转一次,因为两次反转对最终结果没有影响。

基于此,我们从前到后遍历数组。如果遇到0,我们将从当前位置开始反转长度为k的间隔。如果遇到0,剩余间隔的长度小于K,这表明我们无法完成反转。但是,如果每次我们反转当前间隔,反转间隔中的每个数字,时间复杂度为O(n * k),那么毫无疑问超时了。

因此我们需要进行优化,然后考虑每个位置上的元素,它只会受到前一个K-1元素是否反转的影响,因此我们只需要知道前一个k-1元素已经反转了多少次。 我们使用一个队列来存储在i之前的k-1位置反转了多少个元素(队列的长度指反转的次数)。 0反转偶数次为0,则需要反转; 1奇数次反转为0,也需要反转。只有0反转奇数次才变为1,而1反转偶数次为0不需要反转,如果最后k-1位置仍为0,则表示失败。否则,将i添加到队列中并更新答案。

class Solution {
public:
    int minKBitFlips(vector<int>& A, int K) {
        int res=0,n=A.size();
        queue<int> window;//window is used to store the index of the inverted element, the length of the window indicates the number of inversions
        
        for(int i=0;i<n;++i)
        {
            //When the distance between subscripts is greater than k, the team head subscript needs to be removed
            while(!window.empty()&&window.front() + K <= i)
                window.pop();
            
            //The current position's 1 reversing odd times is 0 and needs to be reversed; the current position's 0 reversing even number of times is still 0 or still needs to be reversed
            if(A[i]==window.size()%2)
            {
                if(i+K>n)return -1;
                window.push(i);
                res++;
            }
        }
        return res;
    }
};

 

 

相同的思想,另一种写法

 

class Solution {
public:
    int minKBitFlips(vector<int>& A, int K) {
        int n=A.size();
        int sum=std::accumulate(A.begin(), A.end(), 0);
        if(K==1)return n-sum;
        int res=0;
        int i=0;
        vector<bool>helper(n);
        bool running=false;
        while(i<n){
            if(A[i]==0&&running==false||A[i]==1&&running==true){
                if(i+K-1>=n)return -1;
                helper[i+K-1]=!helper[i+K-1];
                running=!running;
                res++;
            }
            if(helper[i])running=!running;
            i++;
        }
        return res;
    }
};

 

 

class Solution:
    def minKBitFlips(self, A: List[int], K: int) -> int:
        n=len(A)
        if K==1:return n-sum(A)
        res=0
        i=0
        helper=[False]*n
        running=False
        while i<n:
            if A[i]==0 and not running or A[i]==1 and running:
                if i+K-1>=n:return -1
                res+=1
                helper[i+K-1]=not helper[i+K-1]
                running=not running
            if helper[i]:running=not running
            i+=1
        return res

 

posted @ 2021-02-18 11:38  XXXSANS  阅读(222)  评论(0编辑  收藏  举报