列表

详情


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

给定一个二进制数组 nums 和一个整数 k

k位翻转 就是从 nums 中选择一个长度为 k子数组 ,同时把子数组中的每一个 0 都改成 1 ,把子数组中的每一个 1 都改成 0

返回数组中不存在 0 所需的最小 k位翻转 次数。如果不可能,则返回 -1 。

子数组 是数组的 连续 部分。

 

示例 1:

输入:nums = [0,1,0], K = 1
输出:2
解释:先翻转 A[0],然后翻转 A[2]。

示例 2:

输入:nums = [1,1,0], K = 2
输出:-1
解释:无论我们怎样翻转大小为 2 的子数组,我们都不能使数组变为 [1,1,1]。

示例 3:

输入:nums = [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]

 

提示:

相似题目

灯泡开关

原站题解

去查看

上次编辑到这里,代码来自缓存 点击恢复默认模板
class Solution { public: int minKBitFlips(vector<int>& nums, int k) { } };

python3 解法, 执行用时: 1960 ms, 内存消耗: 26 MB, 提交时间: 2023-06-05 10:43:52

class Solution:
    def minKBitFlips(self, nums: List[int], k: int) -> int:
        n = len(nums)
        s = "".join([str(d) for d in nums])
        digit = int("0b" + s, 2)
        ans = 0
        for i in range(n - 1, k - 2, -1):
            if not digit & (1 << i):
                left = (1 << (i + 1)) - 1
                right = (1 << (i - k + 1)) - 1
                digit ^= (left - right)
                ans += 1
        if digit == (1 << n) - 1:
            return ans
        return -1

python3 解法, 执行用时: 188 ms, 内存消耗: 19.6 MB, 提交时间: 2023-06-05 10:43:35

class Solution:
    def minKBitFlips(self, nums: List[int], k: int) -> int:
        n = len(nums)

        # 使用滚动差分数组进行操作累计数与原始值加和
        diff = nums[:]
        for i in range(1, n):
            diff[i] = nums[i]-nums[i-1]

        # 贪心地遍历对每一个当前遇到的0进行k位翻转
        pre = 0
        ans = 0
        for i in range(n-k+1):
            pre += diff[i]
            # 如果状态为奇数则需要再次进行翻转并影响到往后k个数
            if not pre % 2:
                pre += 1
                ans += 1
                if i+k < n:
                    diff[i+k] -= 1

        # 检验剩下的最后k个数是否全为0
        for i in range(n-k+1, n):
            pre += diff[i]
            if not pre % 2:
                return -1
        return ans

python3 解法, 执行用时: 128 ms, 内存消耗: 21.1 MB, 提交时间: 2023-06-05 10:43:04

class Solution:
    def minKBitFlips(self, nums: List[int], k: int) -> int:
        n = len(nums)
        q = collections.deque()
        res = 0
        for i in range(n):
            if q and i >= q[0] + k:
                q.popleft()
            if len(q) % 2 == nums[i]:
                if i +  k > n: return -1
                q.append(i)
                res += 1
        return res

javascript 解法, 执行用时: 92 ms, 内存消耗: 50 MB, 提交时间: 2023-06-05 10:42:06

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number}
 */
var minKBitFlips = function(nums, k) {
    const n = nums.length;
    const diff = new Array(n + 1).fill(0);
    let ans = 0, revCnt = 0;
    for (let i = 0; i < n; i++) {
        revCnt += diff[i];
        if ((nums[i] + revCnt) % 2 === 0) {
            if ((i + k) > n) {
                return -1;
            }
            ++ans;
            ++revCnt;
            --diff[i + k]
        }
    }
    return ans;
};

javascript 解法, 执行用时: 124 ms, 内存消耗: 50.3 MB, 提交时间: 2023-06-05 10:41:44

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number}
 */
var minKBitFlips = function(nums, k) {
    const n = nums.length;
    const diff = new Array(n + 1).fill(0);
    let ans = 0, revCnt = 0;
    for (let i = 0; i < n; i++) {
        revCnt ^= diff[i];
        if (nums[i] === revCnt) { // nums[i] ^ revCnt == 0
            if ((i + k) > n) {
                return -1;
            }
            ++ans;
            revCnt ^= 1;
            diff[i + k] ^= 1;
        }
    }
    return ans;
};

javascript 解法, 执行用时: 80 ms, 内存消耗: 49.5 MB, 提交时间: 2023-06-05 10:41:23

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number}
 */
var minKBitFlips = function(nums, k) {
    const n = nums.length;
    let ans = 0, revCnt = 0;
    for (let i = 0; i < n; ++i) {
        if (i >= k && nums[i - k] > 1) {
            revCnt ^= 1;
            nums[i - k] -= 2; // 复原数组元素,若允许修改数组 nums,则可以省略
        }
        if (nums[i] == revCnt) {
            if (i + k > n) {
                return -1;
            }
            ++ans;
            revCnt ^= 1;
            nums[i] += 2;
        }
    }
    return ans;
};

golang 解法, 执行用时: 160 ms, 内存消耗: 7.4 MB, 提交时间: 2023-06-05 10:41:09

func minKBitFlips(nums []int, k int) (ans int) {
    n := len(nums)
    revCnt := 0
    for i, v := range nums {
        if i >= k && nums[i-k] > 1 {
            revCnt ^= 1
            nums[i-k] -= 2 // 复原数组元素,若允许修改数组 nums,则可以省略
        }
        if v == revCnt {
            if i+k > n {
                return -1
            }
            ans++
            revCnt ^= 1
            nums[i] += 2
        }
    }
    return
}

golang 解法, 执行用时: 148 ms, 内存消耗: 8.1 MB, 提交时间: 2023-06-05 10:40:58

func minKBitFlips(nums []int, k int) (ans int) {
    n := len(nums)
    diff := make([]int, n+1)
    revCnt := 0
    for i, v := range nums {
        revCnt ^= diff[i]
        if v == revCnt { // v^revCnt == 0
            if i+k > n {
                return -1
            }
            ans++
            revCnt ^= 1
            diff[i+k] ^= 1
        }
    }
    return
}

golang 解法, 执行用时: 108 ms, 内存消耗: 8.1 MB, 提交时间: 2023-06-05 10:40:46

func minKBitFlips(nums []int, k int) (ans int) {
    n := len(nums)
    diff := make([]int, n+1)
    revCnt := 0
    for i, v := range nums {
        revCnt += diff[i]
        if (v+revCnt)%2 == 0 {
            if i+k > n {
                return -1
            }
            ans++
            revCnt++
            diff[i+k]--
        }
    }
    return
}

java 解法, 执行用时: 5 ms, 内存消耗: 52.7 MB, 提交时间: 2023-06-05 10:40:30

// 差分数组
class Solution {
    public int minKBitFlips(int[] nums, int k) {
        int n = nums.length;
        int[] diff = new int[n + 1];
        int ans = 0, revCnt = 0;
        for (int i = 0; i < n; ++i) {
            revCnt += diff[i];
            if ((nums[i] + revCnt) % 2 == 0) {
                if (i + k > n) {
                    return -1;
                }
                ++ans;
                ++revCnt;
                --diff[i + k];
            }
        }
        return ans;
    }
}

java 解法, 执行用时: 3 ms, 内存消耗: 53 MB, 提交时间: 2023-06-05 10:40:17

// 差分数组
class Solution {
    public int minKBitFlips(int[] nums, int k) {
        int n = nums.length;
        int[] diff = new int[n + 1];
        int ans = 0, revCnt = 0;
        for (int i = 0; i < n; ++i) {
            revCnt ^= diff[i];
            if (nums[i] == revCnt) { // nums[i] ^ revCnt == 0
                if (i + k > n) {
                    return -1;
                }
                ++ans;
                revCnt ^= 1;
                diff[i + k] ^= 1;
            }
        }
        return ans;
    }
}

java 解法, 执行用时: 4 ms, 内存消耗: 57.1 MB, 提交时间: 2023-06-05 10:39:59

// 滑动窗口
class Solution {
    public int minKBitFlips(int[] nums, int k) {
        int n = nums.length;
        int ans = 0, revCnt = 0;
        for (int i = 0; i < n; ++i) {
            if (i >= k && nums[i - k] > 1) {
                revCnt ^= 1;
                nums[i - k] -= 2; // 复原数组元素,若允许修改数组 nums,则可以省略
            }
            if (nums[i] == revCnt) {
                if (i + k > n) {
                    return -1;
                }
                ++ans;
                revCnt ^= 1;
                nums[i] += 2;
            }
        }
        return ans;
    }
}

cpp 解法, 执行用时: 100 ms, 内存消耗: 103.6 MB, 提交时间: 2023-06-05 10:39:41

// 滑动窗口
class Solution {
public:
    int minKBitFlips(vector<int>& nums, int k) {
        int n = nums.size();
        int ans = 0, revCnt = 0;
        for (int i = 0; i < n; ++i) {
            if (i >= k && nums[i - k] > 1) {
                revCnt ^= 1;
                nums[i - k] -= 2; // 复原数组元素,若允许修改数组 nums,则可以省略
            }
            if (nums[i] == revCnt) {
                if (i + k > n) {
                    return -1;
                }
                ++ans;
                revCnt ^= 1;
                nums[i] += 2;
            }
        }
        return ans;
    }
};

cpp 解法, 执行用时: 156 ms, 内存消耗: 108.3 MB, 提交时间: 2023-06-05 10:39:24

class Solution {
public:
    int minKBitFlips(vector<int>& nums, int k) {
        int n = nums.size();
        vector<int> diff(n + 1);
        int ans = 0, revCnt = 0;
        for (int i = 0; i < n; ++i) {
            revCnt ^= diff[i];
            if (nums[i] == revCnt) { // nums[i] ^ revCnt == 0
                if (i + k > n) {
                    return -1;
                }
                ++ans;
                revCnt ^= 1;
                diff[i + k] ^= 1;
            }
        }
        return ans;
    }
};

cpp 解法, 执行用时: 124 ms, 内存消耗: 108.3 MB, 提交时间: 2023-06-05 10:39:15

// 差分数组
class Solution {
public:
    int minKBitFlips(vector<int>& nums, int k) {
        int n = nums.size();
        vector<int> diff(n + 1);
        int ans = 0, revCnt = 0;
        for (int i = 0; i < n; ++i) {
            revCnt += diff[i];
            if ((nums[i] + revCnt) % 2 == 0) {
                if (i + k > n) {
                    return -1;
                }
                ++ans;
                ++revCnt;
                --diff[i + k];
            }
        }
        return ans;
    }
};

上一题