LeetCode 995. K 连续位的最小翻转次数
作者:互联网
难度困难172收藏分享切换为英文接收动态反馈
在仅包含 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]
解:从前至后遍历,考虑当前值是否需要反转。
若当前值之前的k位内共有m%2==1次反转,则当前位也会跟着翻转
若当前位被前k位翻转后是0,则当前位必须翻转,反之不翻转
又最后K位无法翻转,则判断最后K位被前面翻转后是否为1即可。
区间翻转次数用树状数组/差分数组/滑动窗口可以快速求得。
class Solution {
public:
struct BIT {
BIT(int size) {
m_size = size + 10;
buffer = new int[m_size];
memset(buffer, 0, m_size * sizeof(int));
}
~BIT() {
if (buffer) {
delete []buffer;
}
}
int add(int pos, int val) {
for (;pos < m_size; pos += (pos & -pos)) buffer[pos] += val;
return 0;
}
int get(int pos) {
int ret = 0;
for (;pos; pos -= (pos & -pos)) ret += buffer[pos];
return ret;
}
int *buffer = nullptr;
size_t m_size = 0;
};
int minKBitFlips(vector<int>& A, int K) {
A.insert(A.begin(), 0);
BIT Tree(A.size());
int ret = 0;
for (int i = 1; i < A.size(); ++i) {
int fst = Tree.get(std::max(i - K, 0)), lst = Tree.get(i);
int now = (lst - fst) % 2;
if (now && A[i] == 1 || (!now && A[i] == 0)) {
if (i > A.size() - K) {
return -1;
}
++ret;
Tree.add(i, 1);
}
}
return ret;
}
};
标签:995,int,pos,ret,buffer,翻转,LeetCode,size 来源: https://blog.csdn.net/Zeolim/article/details/113855089