【LeetCode】995. Minimum Number of K Consecutive Bit Flips (C++)


Source of topic: https://leetcode-cn.com/problems/minimum-number-of-k-consecutive-bit-flips/

Title description

In the array A containing only 0 and 1 , a K bit flip involves selecting a (continuous) sub-array of length K , and changing each 0 in the sub-array to 1 and changing each 1 to 0.

Returns the minimum number of K bit flips required so that the array has no elements with value 0. If it is not possible, return -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

General idea

  • The meaning of the question is easy to understand. When dealing with problems such as continuous sub-arrays, the sliding window approach should be the first thing that comes to mind. In this question, because the input data is only 0 and 1, the final processing is all 1 and the sub-array It is continuous, so you can use queues to implement sliding windows
  • When A[i] == 0, and the current queue.size()% 2 == 0, it means that A[i] is 0, and after an even number of flips, the result remains unchanged, so the current needs to be flipped once. Push index into the queue
  • When A[i] != 0, and the current queue.size()% 2 != 0, it means that A[i] is 1, and after an odd number of flips, the result is ~A[i], so the current need Flip once, then push index into the queue
  • In summary, the result of even number flipping through even number of times and odd number flipping through odd number of times is 0. The judgment that the flipping is needed can be summarized as A[i] == queue.size()% 2

Queue realizes the idea of ​​sliding window

  • Maintain a queue, if the current loop nums[i] == queue.size()% 2, put the subscript i into the queue queue, and then traverse the elements to get the queue end element of the queue (below the previous flipped position) Index), if the current index i>queue.front (the index of the element that needs to be flipped first) + K, the index needs to be popped out, because the window has already exceeded K at this time
  • If the current element needs to be flipped, but i + K> len, and the number of elements after the subscript i is less than K, it means that it cannot be flipped, then it means that it is impossible to flip all the current array to 1
class Solution {
    
    
public:
    int minKBitFlips(vector<int>& A, int K) {
    
    
        queue<int> q;
        int len = A.size();
        int cnt = 0;
        for(int i = 0 ; i < len; ++i){
    
    
            if(q.front() + K <= i && !q.empty()){
    
    
                q.pop();
            }
            if(q.size() % 2 == A[i]){
    
    
                if(i + K > len) return -1;
                q.push(i);
                ++cnt;
            }
        }
        return cnt;
    }
};

Complexity analysis

  • Time complexity: O(n). n is the length of the array
  • Space complexity: O(K). In principle, the elements in the queue can only reach K at most

Difference thinking

  • In this question, if you blindly flip 0 to 1, it will cause a timeout and simulate flipping the array in place. This inspired us not to consider flipping the numbers, but counting the number of times each number needs to be flipped. For a flip operation, it is equivalent to the number of flips of all numbers in the sub-array +1
  • We can maintain a difference array diff, where diff[i] represents the difference in the number of flips of two adjacent elements A[i-1] and A[i]. For the interval [l,r], all elements are +1, Using the feature of difference, this operation can be done in O(1), just increase diff[l] by 1, diff[r + 1] by 1
  • When traversing to A[i], if A[i] + cnt is an even number, it needs to be flipped (the article initially analyzed the conditions when flipping is required), the flipping interval is [i, i+K-1], and the corresponding difference processing is diff[i] += 1, diff[i + K-1] -= 1
  • If i+k>len, the flip operation cannot be performed, and -1 is returned

AC code

class Solution {
    
    
public:
    int minKBitFlips(vector<int>& A, int K) {
    
    
        int len = A.size();
        vector<int> diff(len + 1);
        int ans = 0, cnt = 0;
        for(int i = 0 ; i < len; ++i){
    
    
            cnt += diff[i];
            if((A[i] + cnt) % 2 == 0){
    
    
                if(i + K > len) return -1;
                ++ans;
                ++cnt;
                --diff[i + K];
            }            
        }
        return ans;
    }
};

Complexity analysis

  • Time complexity: O(n). n is the length of the array
  • Space complexity: O(n). n is the length of the array, because a difference array diff needs to be maintained, and the length is n

Guess you like

Origin blog.csdn.net/lr_shadow/article/details/113938138