k连续位置的最小翻转次数

184 阅读2分钟

题目

滑动窗口

public class Main {
    public static void main(String[] args) {

        Main main = new Main();
        int [] nums = new int[] {0, 0, 0, 1, 0, 1, 1, 0};
        main.minKBitFlips(nums, 3);
    }

    public int minKBitFlips(int[] A, int K) {

        // 利用队列判断当前位置的元素是否需要翻转
        Queue<Integer> queue = new LinkedList<>();

        int count = 0;
        // 遍历A数组
        for (int i = 0; i < A.length; i ++) {

            if (queue.size() > 0) {
                // 如果队列中有元素,就表明队列的头部元素的值(对应数组中的索引), 加上K包含当前i, 说明当前位置i被翻转过一次
                // 那么在头部元素之后的值, 肯定就包含当前i
                // 所以队列的长度就是当前位置i被翻转过的次数
                if ((A[i] + queue.size()) % 2 == 0 ) {
                    // 翻转一次就代表当前数字加1, 如果最后为偶数, 表示当前位置需要翻转
                    if (i + K <= A.length) {
                        queue.offer(i);
                        count ++;
                    } else {
                        return -1;
                    }

                }

                // 判断队列的头部元素是否需要被移除
                if (queue.peek() + K == i + 1) {
                    // 弹出顶部元素
                    queue.poll();
                }
            } else {
                // 队列如果为空 只跟当前值有关
                if (A[i] == 0) {
                    if (i + K <= A.length) {
                        if (K > 1) {
                            // 只有K > 1才有使用队列的必要
                            queue.offer(i);
                        }
                        count ++;
                    } else {
                        return -1;
                    }

                }
            }
        }
        return count;
    }

}

基本思路

  1. 以长度K为单位进行翻转

  2. 每个位置的翻转情况, 只和当前位置之前元素的翻转有关, 和之后的无关, 因此可以从左向右遍历数字, 逐个判断每个位置的翻转情况

  3. 以某个索引下标为起始的翻转只应该进行一次, 因为如果某个索引开头的子数组被翻转两次, 那么该索引位置的元素相当于没翻转. 例如[0, 0, 1]这个数组, 当K为2时, 以索引1开头的数组, 只会进行一次翻转, 也就是翻转[0, 1], 但是不代表索引1的元素只会被翻转一次, 因为如果我翻转[0, 0]索引1被翻转了一次, 我再翻转索引1开始的子数组, 索引1就相当于翻转了两次.

  4. 按顺序从左到右翻转, 和你乱序翻转, 最后翻转次数是一致的

  5. 如果你遵循条件3, 那么你得到的翻转次数就是最小次数

  6. 并不真正的去翻转元素, 而是记录每个元素曾经被翻转的次数, 再根据当前元素的值来判断该位置的元素是否需要被翻转(例如队列来实现判断)