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

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

贪心+模拟

初步的想法,从头开始遍历,A[i]碰到0就需要翻转一下从i开始的长度为K的子数组,于是模拟下反转的过程。

class Solution {
    int[] A;
    int K, n, res;
    public int minKBitFlips(int[] A, int K) {
        this.A = A;
        this.K = K;
        this.n = A.length;
        for(int i = 0; i < n - K; i++)
            if(A[i] == 0) flip(i);
        int sum = 0;
        for(int i = n - K; i < n; i++) sum += A[i];
        return sum == 0 ? res + 1 : (sum == K ? res : -1);
    }
    void flip(int index){
        res++;
        for(int i = index; i < index + K; i++) A[i] = 1 - A[i];
    }
}

时间复杂度 O ( N K ) O(NK) O(NK)超时

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y3XiUJgn-1613617074276)(https://pic.leetcode-cn.com/1613616642-FAjsMW-image.png)]

贪心+计算是否翻转

使用一个变量 f l i p flip flip来表示当前的翻转次数,若为偶数则相当于不变,奇数相当于翻转。这里利用了模2加法相当于异或的操作,是否翻转,1表示翻转,0表示不变。
那么,每次碰到0就需要把flip翻转一下,表示后续的数字需要翻转,但是需要保证到K的时候就不需要这次翻转了,因此需要记录一下:通过将A[i] += 2来表示从i开始到i+K的数组需要翻转,这样的话,就可以遍历到i时,先判断一下A[i - K]是否大于1,若大于1表示这个位置之前翻转过,需要取消之前的影响,把flip翻转一下。

class Solution {
    public int minKBitFlips(int[] A, int K) {
        int n = A.length, res = 0, flip = 0;
        for(int i = 0; i < n; i++){
            if(i >= K && A[i - K] > 1) flip ^= 1;   //模2加法相当于异或
            if((A[i] ^ flip) == 0){
                if(i + K > n) return -1;
                flip ^= 1;
                res++;
                A[i] += 2;
            }
        }
        return res;
    }

}

时间复杂度

遍历一遍 O ( N ) O(N) O(N)

空间复杂度

使用常数级别额外空间 O ( 1 ) O(1) O(1)

我的博客:https://me.csdn.net/qq_20067165?ref=miniprofile

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值