Leetcode 995. K 连续位的最小翻转次数——差分数组

引入

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

内容不做赘述,这道题如果用模拟的方式是会超时的:也就是在循环的过程中,对于K大小的数组,每一位与1取异或。
可以看到这样的效率很低,其复杂度为O(KN)。

更好的办法是用差分数组。

差分数组

如果给你一个包含5000万个元素的数组,然后会有频繁区间修改操作,那什么是频繁的区间修改操作呢?比如让第1个数到第1000万个数每个数都加上1,而且这种操作时频繁的。

此时你应该怎么做?很容易想到的是,从第1个数开始遍历,一直遍历到第1000万个数,然后每个数都加上1,如果这种操作很频繁的话,那这种暴力的方法在一些实时的系统中可能就拉跨了。

比如我们现在有一个数组reAreA={0,2,5,4,9,7,10,0},差分数组的计算公式为:
在这里插入图片描述

这时候,如果构造差分数组:

index01234567
arr025497100
diff023-15-23-10

构造差分数组的效果,我们可以看下面一个例子,比如对于区间[1-4]整体加上5,除开暴力的加上去,差分数组只需要在diff[1]上加5,在diff[5]上减去5:

index01234567
arr025497100
暴力02+55+54+59+57100
diff02+53-15-2-53-10

可以看到,无论区间K有多大,暴力的复杂度是O(K),而差分的复杂度是O(2)。

现在来看真实的计算:
如何根据差分数组diff来推测reA中某一个位置的值呢?
比如求reA[1],我们知道,reA[1]-reA[0]=diff[1]=>reA[1]=diff[1]+reA[0]=>reA[1]=2+5+0=7

现在就知道差分数组的作用了,就是以空间换时间。

题解

我们用差分数组diff来表示两个数字之间翻转次数的差值。由于第i位的0需要翻转成为1,那么我们需要将diff[i]++,将diff[i+k]--来表示差分的值。
另外,由于diff[i]的值有变化,对于某一位i的值,不能简单的用原先的0或者1来判断了,需要与diff[i]结合起来。

import java.util.*;

class Solution {
    public int minKBitFlips(int[] nums, int k) {
        int[] diff = new int[nums.length+1];

        int revCnt = 0;
        int count = 0;
        for (int i = 0; i < nums.length; i++) {
            revCnt += diff[i];
            if (((revCnt + nums[i]) & 1) == 0) {
                if (i + k > nums.length) return -1;//越界了
                // 需要翻转
                // diff[i]++; // diff[i]之后不会用到,所以注释掉
                revCnt++; //由diff[i]++引起,
                diff[i + k]--;
                count++;
            }
        }
        return count;
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值