码迷,mamicode.com
首页 > 其他好文 > 详细

995. Minimum Number of K Consecutive Bit Flips (2021/2/18每日一题)

时间:2021-02-20 12:13:50      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:css   https   标签   位置   idt   red   ble   loading   tps   

995. Minimum Number of K Consecutive Bit Flips

In an array A containing only 0s and 1s, a K-bit flip consists of choosing a (contiguous) subarray of length K and simultaneously changing every 0 in the subarray to 1, and every 1 in the subarray to 0.

Return the minimum number of K-bit flips required so that there is no 0 in the array.  If it is not possible, return -1.

 

Example 1:

Input: A = [0,1,0], K = 1
Output: 2
Explanation: Flip A[0], then flip A[2].
Example 2:

Input: A = [1,1,0], K = 2
Output: -1
Explanation: No matter how we flip subarrays of size 2, we can‘t make the array become [1,1,1].
Example 3:

Input: A = [0,0,0,1,0,1,1,0], K = 3
Output: 3
Explanation:
Flip A[0],A[1],A[2]: A becomes [1,1,1,1,0,1,1,0]
Flip A[4],A[5],A[6]: A becomes [1,1,1,1,1,0,0,0]
Flip A[5],A[6],A[7]: A becomes [1,1,1,1,1,1,1,1]
 

Note:

1 <= A.length <= 30000
1 <= K <= A.length

 

题目大意:题目要求将窗口K内的所有数字反转,0变1,1变0,最后要求整个数组不存在0,问最低反转多少次。

思路:看到题时一直在想:最低反转多少次?用dp?好像怎么也推不出转移公式,因为前面有0就必须反转,不存在需不需要反转的问题。用greedy? 看了下标签果然,贪心+滑动窗口。用一个与输入等长的数组flip记录每位数字是否需要反转,用一个变量cur记录当前位曾经反转的次数,用变量res记录最终反转多少次。

用例子来说明:[0,0,0,1,0,1,1,0], K=3

注:每次计算i位时,为以i为起始长度为K的窗口,图中标黄色的长度为K的窗口为对当前位有反转影响的窗口。比如第五步判断i=3时,计算窗口i=3,4,5位是否需要被反转, 而对3,4,5位是否需要被反转结果有影响的窗口为第五步图中标黄的窗口i=1,2,3.

第一步:初始化 cur = 0, res = 0, flip = 0

技术图片

 

第二步:判断i=0时,此时cur为初始值0,并且i <K未达到窗口长度,因此cur即为当前数字曾经反转的次数,cur % 2 == 0(即相当于未曾被反转过)。A[0] = 0,题目要求不存在0,因此i=0位需要被反转。

更新cur = 1, res = 1, flip[0] = 1;此时窗口长度为1.

技术图片

 

 第三步:判断i=1时,此时cur = 1, i<K未达到窗口长度,cur为当前数字曾经反转的次数,cur % 2 = 1(即当前数字已被反转过,而且未被反转回来,即1->0, 0->1),A[1] = 0,因此此时 i=1位已经被反转为1,不需要再进行操作。当前窗口长度为2.

技术图片

 

 第四步:与第三步同,窗口长度为3==K

技术图片

 第五步:判断i=3时,当前cur=1, 因为滑到i=3时窗口长度为4>K,第i-K=0位的反转不会影响到i=3的位置,只有i =1,2位的反转操作窗口包含了i=3位。因此cur需要减掉对第i-K位的反转次数才能得到当前位曾经被反转的次数。因此cur = cur -flip[i-K] = 1-1=0. 即i=3位未被反转过(it make sense, 因为以i=1, i=2位起始的窗口都未作反转操作)。但A[3] = 1已经是1了,因此还是不需要进行操作,只需要更新cur值:

技术图片

 

 第六步:判断i=4时,cur = 0, cur = cur-flip[i-K] = 0-0=0, 当前值未被反转过,且A[4] = 0,因此需要进行反转操作,更新cur = cur+1=1, res = res+1=2, flip[4] = 1:

技术图片

 

 第七步:判断i=5时,cur = 1, cur = cur - flip[i-K] =1-0=1,  cur % 2 = 1即当前值已经被反转(0->1, 1->0),且A[5] = 1, 说明A[5]经过前面的反转已经变为0了,因此需要再次被反转成为1.

更新cur = cur+1=2, res = res+1=3, flip[5] = 1: 

注:因为此时i+K = A.size(),因此以i=5起始的窗口为最后一个窗口,其后的窗口都小于K. 因此也是反转操作的最后一个窗口。

技术图片

 

 第七步:判断i=6, cur = 2, cur = cur-flip[i-K] = 2-0=2, cur % 2 = 0,即当前值虽然曾经被反转过,但反转过偶数次,即经过前面窗口内值的反转后值不变。A[6] = 1:

注:因为i +K=6+3 >A.size(),因此此位不管是0是1都不能进行反转操作,为1即可向后判断,为0则直接返回-1.

技术图片

 

 第八步:判断i=7, cur = 2, cur = cur-flip[i-K] = 2-1 = 1, cur % 2 = 1,  即当前值已被反转为不同的值(0->1, 1->0), A[7] = 0,经反转后变为1

技术图片

 

第九步:返回res值。代码如下:

 1 class Solution {
 2 public:
 3     int minKBitFlips(vector<int>& A, int K) {
 4         int res = 0, cur = 0;
 5         vector<int> flip(A.size(), 0);
 6         for(int i=0; i<A.size(); i++){
 7             if(i >= K) cur -= flip[i-K];
 8             if((A[i] == 0 && cur % 2 == 0) ||
 9                 (A[i] == 1 && cur % 2 == 1)){
10                     if(i > A.size()-K){
11                         return -1;
12                     } else {
13                         res++;
14                         cur++;
15                         flip[i] = 1;
16                     }
17                 }
18         }
19         return res;
20     }
21 };

 

画图太痛苦了~画的我想吐血

 

995. Minimum Number of K Consecutive Bit Flips (2021/2/18每日一题)

标签:css   https   标签   位置   idt   red   ble   loading   tps   

原文地址:https://www.cnblogs.com/boligongzhu/p/14416548.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!