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

在仅包含 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

思路:

首先,贪心算法,从左开始遍历,第一个部不为1的数总是需要被翻的。

其次,采用滑动窗口方法,使用队列模拟滑动窗口,队列的长度表示遍历到i时,i需要反转的次数。

当 A[i] 为 0,如果 i 位置被翻转了偶数次,那么翻转后仍是 0,当前元素需要翻转;
当 A[i] 为 1,如果 i 位置被翻转了奇数次,那么翻转后变成 0,当前元素需要翻转。
由上可知,如果 queue.size()%2==A[i],则当前元素需要翻转,且当i+K>N时,表示无论如何翻转都不可能为1 。

class Solution {
    public int minKBitFlips(int[] A, int K) {
        Queue<Integer> window = new LinkedList<>(); 
        int count = 0;
        for(int i = 0; i < A.length; i++){
            if(!window.isEmpty() && window.peek() + K <= i) {
                window.poll();
            }
            if(window.size() %2 == A[i]) {
                if (i + K > A.length){
                    return -1;
                }
                window.add(i);
                count++;
            }
        }
        return count;
    }
}

 

posted on 2021-02-27 23:18  joannae  阅读(72)  评论(0编辑  收藏  举报

导航