zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    弹性盒子
    bzoj4237 稻草人
    bzoj2654 tree
    bzoj4813 [Cqoi2017]小Q的棋盘
    bzoj1014 [JSOI2008]火星人
    bzoj3242 [Noi2013]快餐店
    bzoj4025 二分图
    bzoj3237 [Ahoi2013]连通图
    bzoj3244 [Noi2013]树的计数
    bzoj2431 [HAOI2009]逆序对数列
  • 原文地址:https://www.cnblogs.com/xxxsans/p/14411193.html
Copyright © 2011-2022 走看看