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

  • 1. 题目描述
  • 2. 贪心(Greedy)
    • 2.1 解题思路
    • 2.2 实例代码
  • 3. 参考资料

1. 题目描述

在仅包含 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 <= A.length <= 30000
  • 1 <= K <= A.length

题目链接:中文题目;英文题目

2. 贪心(Greedy)

2.1 解题思路

题目要求把所有的0变成1,那么一个比较直接的思路就是:遍历整个数组,遇到0(序号i),则把nums[i] ~ nums[i + K - 1]全部反转,计数(count)加一,这样我们保证nums[i]一定为1,那么我们继续从i + 1开始向后检查;如果遇到0,但i + K -1 >= 数组长度(len)那么表示当前没有足够的数进翻转,所以没办法把所有的0变成1,返回-1即可。下面举两个例子进行说明:

[1,0,1,0], k = 2

i = 1时进行翻转,[1,0,1,0] -> [1,1,0,0],当i = 2时又翻转,[1,1,0,0] -> [1,1,1,1],后面全部都是1,所以返回2即可。

[0,0,1,0], k = 2

i = 0翻转,[0,0,1,0] -> [1,1,1,0],当i = 3时,i + k - 1 >= 3,后面没有足够的数进行翻转,所以返回-1;

这种思路有一个不足的地方,就是我们需要向后翻转数字,再回到i + 1的位置,这样会浪费一定的时间。从上面的例子我们可以发现:

当翻转nums[i] ~ nums[i - K - 1]后,如果num[i + 1] ~ nums[i + K - > 1]有0才需要再一次翻转,否则是不需要翻转的,换个角度,如果我们不变换原数组,那么最开始是遇到0需要翻转,翻转之后,需要遇到1才需要翻转。

举个例子来说明:

[1,0,1,0], k = 2

第一次翻转后:[1,1,0,1],下一次翻转的位置是i = 2,翻转后是0,原数组是1;反过来,如果翻转后是1,那原数组就是0。根据这个特点,我们就不用真的去翻转数字,可以初始化一个flip去记录下一个需要翻转的数。只是这样有一个问题需要解决:当抵达nums[i + K],需要将flip重置会原来的状态,所以初始化一个hints数组,如果i需要翻转,那么hints[i + K]则标记为1,表示边界位置,每次检查hints,如果为1,则重置flip。

这里我们使用异或运算进行标记:0 ^ 0 = 0, 0 ^ 1 = 1,所以^ 1表示重置状态。此部分对应代码:2.2.1 使用额外空间。

另外,我们可以不使用额外空间,直接在原数组进行标记。通过上面的讲解,我们可以知道翻转的数字是0或者1,也可以称之为偶数和奇数,所以同样初始化一个flip = 0,当nums[i] % 2 == flip,表示对应需要翻转的数, 则nums[i] += 2,flip++。对于边界的标记,需要向前标记:检查nums[i - K] > 1,如果为真,表示i为边界,nums[i - K] -= 2, flip减一。总之,和上面的方法相比,对flip加减相当于 flip ^= 1和flip ^= hints[i],nums[i] % 2 == flip相当于A[i] == flip。此部分对应代码:2.2.2 无需使用额外空间。

最后举一个例子再说明一下:

[1,0,0,1], k = 2

  1. 初始化flip = 0;
  2. i = 1,flip % 2 = 0 == 0,则[1,0,0,1] -> [1, 2, 0, 1],flip = 1;
  3. i = 2,flip % 2 = 1 != 0;
  4. i = 3,nums[i - k] > 1,nums[i - k] -= 2, 则[1, 2, 0, 1] -> [1, 0, 0, 1],flip = 0,flip % 2 = 0 != 1,返回1即可。

2.2 实例代码

2.2.1 使用额外空间

class Solution {public:int minKBitFlips(vector<int>& A, int K) {int len = A.size(), ans = 0, flip = 0;vector<int> hints(len, 0);for (int i = 0; i < len; i++) {flip ^= hints[i]; // 检查是否到达某个子串的边界if (A[i] == flip) {ans++;if (i + K > len) return -1;flip ^= 1; // 下一个需要翻转的数字: 0 -> 1, 1 -> 0if (i + K < len) hints[i + K] ^= 1; // 标记边界}}return ans;}
};

2.2.2 无需使用额外空间

class Solution {public:int minKBitFlips(vector<int>& A, int K) {int len = A.size(), ans = 0, flip = 0;for (int i = 0; i < len; i++) {if (i >= K && A[i - K] > 1) { flip--; A[i - K] -= 2; } // 检查是否到达某个子串的边界if (flip % 2 == A[i]) {if (i + K > len) return -1;A[i] += 2; // 标记边界flip++;ans++;}}return ans;}
};

3. 参考资料

  1. 995. Minimum Number of K Consecutive Bit Flips
  2. [Java/C++/Python] One Pass and O(1) Space

995. Minimum Number of K Consecutive Bit Flips(K 连续位的最小翻转次数)解法(C++ 注释)相关推荐

  1. LeetCode-995. K连续位的最小翻转次数(Minimum Number of K Consecutive Bit Flips)

    K连续位的最小翻转次数 在仅包含 0 和 1 的数组 A 中,一次 K 位翻转包括选择一个长度为 K 的(连续)子数组,同时将子数组中的每个 0 更改为 1,而每个 1 更改为 0. 返回所需的 K ...

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

    链接:995. K 连续位的最小翻转次数 题解: https://leetcode-cn.com/problems/minimum-number-of-k-consecutive-bit-flips/ ...

  3. Leetcode-滑窗/差分数组-995. K 连续位的最小翻转次数

    题目995. K 连续位的最小翻转次数: 题解: 方法一:队列 + 滑窗(from 负雪明烛) class Solution { public:int minKBitFlips(vector<i ...

  4. leetcode 995. K 连续位的最小翻转次数(贪心算法)

    在仅包含 0 和 1 的数组 A 中,一次 K 位翻转包括选择一个长度为 K 的(连续)子数组,同时将子数组中的每个 0 更改为 1,而每个 1 更改为 0. 返回所需的 K 位翻转的最小次数,以便数 ...

  5. LeetCode 995. K 连续位的最小翻转次数(差分思想)

    文章目录 1. 题目 2. 解题 1. 题目 在仅包含 0 和 1 的数组 A 中,一次 K 位翻转包括选择一个长度为 K 的(连续)子数组,同时将子数组中的每个 0 更改为 1,而每个 1 更改为 ...

  6. leetCode-995:K 连续位的最小翻转次数

    题目描述: 在仅包含 0 和 1 的数组 A 中,一次 K 位翻转包括选择一个长度为 K 的(连续)子数组,同时将子数组中的每个 0 更改为 1,而每个 1 更改为 0. 返回所需的 K 位翻转的最小 ...

  7. 995.K连续位的最小翻转次数(唯唯诺诺)

    如题: 在仅包含 0 和 1 的数组 A 中,一次 K 位翻转包括选择一个长度为 K 的(连续)子数组,同时将子数组中的每个 0 更改为 1,而每个 1 更改为 0. 返回所需的 K 位翻转的最小次数 ...

  8. LeetCode 871. Minimum Number of Refueling Stops 最少加油次数

    LeetCode 871. Minimum Number of Refueling Stops 本题是LeetCode 871题,最少加油次数. 题目描述 A car travels from a s ...

  9. LeetCode——1888. 使二进制字符串字符交替的最少反转次数(Minimum Number of Flips to Make the Binary ...)[中等]——分析及代码(Java)

    LeetCode--1888. 使二进制字符串字符交替的最少反转次数[Minimum Number of Flips to Make the Binary String Alternating][中等 ...

  10. LeetCode 202次周赛 1553. Minimum Number of Days to Eat N Oranges

    1553. Minimum Number of Days to Eat N Oranges 题目描述 思路分析 弱智动态规划 可行的动态规划 直觉上正确的思路 代码实现 证明正确性 复杂度分析 总结 ...

最新文章

  1. python的turtle绘图体系入门必看(二)
  2. awt简单应用 panel面板
  3. CentOS 设置网络(修改IP 网关 DNS)上网
  4. 如何用 Java 实现简单的区块链
  5. 春节添彩 福州花卉市场现“买花潮”
  6. 一名即将大三的小伙子在疫情期间的思考与总结
  7. 用UIpickView实现省市的联动
  8. 作者:黄媛洁(1992-),女,食品安全大数据技术北京市重点实验室、北京工商大学计算机与信息工程学院硕士生...
  9. java中的集合_你真的了解Java中的集合类么?
  10. 下行文格式图片_收藏!公文写作格式大全(附示例图)
  11. JavaScript多继承(转载)
  12. 密码学Cryptology
  13. 新能源汽车行业研究及2020年策略报告:拐点之年
  14. 手机变速齿轮_变速齿轮手机版下载|变速齿轮游戏加速器官方最新版v1.2下载 _当游网...
  15. mongodb mapreduce分析
  16. 输出今天日期,以yyyy-mm-dd方式输出
  17. Python实现自动挂机脚本(基础篇)
  18. 图像处理中像素和毫米的换算
  19. FLOW2000破解,完美长期使用
  20. Java Web高级面试题(二)

热门文章

  1. sop流程图模板_SOP模板-标准操作流程编写程序.doc
  2. VMware用rz传输文件
  3. 中芯国际换帅,事情并不简单
  4. 手把手教你智能硬件开发(一) 我选Arduino
  5. 树莓派B+安装简单版魔镜MagicMirror
  6. 曲线运动与万有引力公式_【知识总结】物理必修二曲线运动与万有引力相关公式和规律...
  7. word小技巧 将图片批量居中
  8. 登高,A股想过重阳节,但是令人遗憾的是,遍插茱萸少一人啊
  9. HTML布局之flex布局
  10. 购物直播系统搭建 新型电商开发方案