995. Minimum Number of K Consecutive Bit Flips(K 连续位的最小翻转次数)解法(C++ 注释)
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
- 初始化flip = 0;
- i = 1,flip % 2 = 0 == 0,则[1,0,0,1] -> [1, 2, 0, 1],flip = 1;
- i = 2,flip % 2 = 1 != 0;
- 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. 参考资料
- 995. Minimum Number of K Consecutive Bit Flips
- [Java/C++/Python] One Pass and O(1) Space
995. Minimum Number of K Consecutive Bit Flips(K 连续位的最小翻转次数)解法(C++ 注释)相关推荐
- LeetCode-995. K连续位的最小翻转次数(Minimum Number of K Consecutive Bit Flips)
K连续位的最小翻转次数 在仅包含 0 和 1 的数组 A 中,一次 K 位翻转包括选择一个长度为 K 的(连续)子数组,同时将子数组中的每个 0 更改为 1,而每个 1 更改为 0. 返回所需的 K ...
- 995. K 连续位的最小翻转次数
链接:995. K 连续位的最小翻转次数 题解: https://leetcode-cn.com/problems/minimum-number-of-k-consecutive-bit-flips/ ...
- Leetcode-滑窗/差分数组-995. K 连续位的最小翻转次数
题目995. K 连续位的最小翻转次数: 题解: 方法一:队列 + 滑窗(from 负雪明烛) class Solution { public:int minKBitFlips(vector<i ...
- leetcode 995. K 连续位的最小翻转次数(贪心算法)
在仅包含 0 和 1 的数组 A 中,一次 K 位翻转包括选择一个长度为 K 的(连续)子数组,同时将子数组中的每个 0 更改为 1,而每个 1 更改为 0. 返回所需的 K 位翻转的最小次数,以便数 ...
- LeetCode 995. K 连续位的最小翻转次数(差分思想)
文章目录 1. 题目 2. 解题 1. 题目 在仅包含 0 和 1 的数组 A 中,一次 K 位翻转包括选择一个长度为 K 的(连续)子数组,同时将子数组中的每个 0 更改为 1,而每个 1 更改为 ...
- leetCode-995:K 连续位的最小翻转次数
题目描述: 在仅包含 0 和 1 的数组 A 中,一次 K 位翻转包括选择一个长度为 K 的(连续)子数组,同时将子数组中的每个 0 更改为 1,而每个 1 更改为 0. 返回所需的 K 位翻转的最小 ...
- 995.K连续位的最小翻转次数(唯唯诺诺)
如题: 在仅包含 0 和 1 的数组 A 中,一次 K 位翻转包括选择一个长度为 K 的(连续)子数组,同时将子数组中的每个 0 更改为 1,而每个 1 更改为 0. 返回所需的 K 位翻转的最小次数 ...
- LeetCode 871. Minimum Number of Refueling Stops 最少加油次数
LeetCode 871. Minimum Number of Refueling Stops 本题是LeetCode 871题,最少加油次数. 题目描述 A car travels from a s ...
- LeetCode——1888. 使二进制字符串字符交替的最少反转次数(Minimum Number of Flips to Make the Binary ...)[中等]——分析及代码(Java)
LeetCode--1888. 使二进制字符串字符交替的最少反转次数[Minimum Number of Flips to Make the Binary String Alternating][中等 ...
- LeetCode 202次周赛 1553. Minimum Number of Days to Eat N Oranges
1553. Minimum Number of Days to Eat N Oranges 题目描述 思路分析 弱智动态规划 可行的动态规划 直觉上正确的思路 代码实现 证明正确性 复杂度分析 总结 ...
最新文章
- python的turtle绘图体系入门必看(二)
- awt简单应用 panel面板
- CentOS 设置网络(修改IP 网关 DNS)上网
- 如何用 Java 实现简单的区块链
- 春节添彩 福州花卉市场现“买花潮”
- 一名即将大三的小伙子在疫情期间的思考与总结
- 用UIpickView实现省市的联动
- 作者:黄媛洁(1992-),女,食品安全大数据技术北京市重点实验室、北京工商大学计算机与信息工程学院硕士生...
- java中的集合_你真的了解Java中的集合类么?
- 下行文格式图片_收藏!公文写作格式大全(附示例图)
- JavaScript多继承(转载)
- 密码学Cryptology
- 新能源汽车行业研究及2020年策略报告:拐点之年
- 手机变速齿轮_变速齿轮手机版下载|变速齿轮游戏加速器官方最新版v1.2下载 _当游网...
- mongodb mapreduce分析
- 输出今天日期,以yyyy-mm-dd方式输出
- Python实现自动挂机脚本(基础篇)
- 图像处理中像素和毫米的换算
- FLOW2000破解,完美长期使用
- Java Web高级面试题(二)