leetcode995(K 连续位的最小翻转次数:贪心算法+差分数组优化)

在仅包含 0 和 1 的数组 A 中,一次 K 位翻转包括选择一个长度为 K 的(连续)子数组,同时将子数组中的每个 0 更改为 1,而每个 1 更改为 0。
返回所需的 K 位翻转的最小次数,以便数组没有值为 0 的元素。如果不可能,返回 -1。

例:
输入: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]

题解:贪心算法+差分数组优化

       要找到最小翻转次数,我们可以使用贪心算法的思想,遍历数组A,当遍历到的数字为0时,则以该数字为起点,翻转长度为K的子数组,若该子数组索引越界,则返回-1,若能遍历完数组A,则返回翻转的总次数。

class Solution {
    public int minKBitFlips(int[] A, int K) {
        int len=A.length;
        int count=0;
        for(int i=0;i<len;i++){
            if(A[i]==0){
                if(i+K-1>=len){
                    return -1;
                }else{
                    for(int j=0;j<K;j++){
                        if(A[i+j]==0){
                            A[i+j]=1;
                        }else{
                            A[i+j]=0;
                        }
                    }
                    count++;
                }
            }
        }
        return count;
    }
}

       该算法的时间复杂度是O(NK),我们可以用差分数组对算法进行优化,使时间复杂度降为O(N)。
       设第i个字符的翻转次数为 f[ i ](i=1,2,3…),设差分数组 int[ ] difference,difference[ 0 ]=f[ 0 ]=0,difference[ i ]=f[ i ]-f[ i-1 ](i!=0),则 f[ i ]=difference[ 0 ]+difference[ 1 ]+…+difference[ i ],当区间[ r , l ]内的所有数字都进行翻转时,只有difference[ r ]增大1与difference[ i+1 ]减小1,其余区间内的差分大小不变,这样极大简化了区间翻转时的算法操作,只需要变化difference[ r ]与difference[ i+1 ]即可。

class Solution {
    public int minKBitFlips(int[] A, int K) {
        int len=A.length;
        int[]difference=new int[len+1];
        int sum=0;
        int ans=0;
        for(int i=0;i<len;i++){
            sum+=difference[i];
            if((A[i]+sum)%2==0){
                if(i+K>len){
                    return -1;
                }
                difference[i+1]++;
                ans++;
                difference[i+K]--;
            }
        }
        return ans;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值