1. 題目
在僅包含 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
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/minimum-number-of-k-consecutive-bit-flips
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。
2. 解題
- 差分思想,用差分數組記錄區間翻轉情況
- 左端點翻轉一次的話,長度爲 K 的區間左端點+1,右端點+1的位置 -1
- 差分數組的前綴和爲每個位置的翻轉次數,翻轉次數爲偶數的話,狀態不變
class Solution {
public:
int minKBitFlips(vector<int>& A, int K) {
int n = A.size();
vector<int> flip(n+1, 0);
int presum = 0;//每個位置的翻轉次數
int ans = 0;
for(int i = 0; i <= n-K; ++i)
{
//前面可以翻的位置
presum += flip[i];
if((A[i]+presum)%2 == 1)//不用再翻了
continue;
else
{
flip[i]++;//左端點+1
ans++;
flip[i+K]--;//差分,右端點+1的位置 -1
presum++;//前綴和更新
}
}
for(int i = n-K+1; i < n; i++)
{
//剩餘的不能再翻了,不足K個
presum += flip[i];
if((A[i]+presum)%2 == 0)
return -1;//有不爲1的,不能滿足全部翻成1
}
return ans;
}
};
224 ms 74.4 MB C++
我的CSDN博客地址 https://michael.blog.csdn.net/
長按或掃碼關注我的公衆號(Michael阿明),一起加油、一起學習進步!