傳送門算法
在僅包含 0 和 1 的數組 A 中,一次 K 位翻轉包括選擇一個長度爲 K 的(連續)子數組,同時將子數組中的每一個 0 更改成 1,而每一個 1 更改成 0。
返回所需的 K 位翻轉的最小次數,以便數組沒有值爲 0 的元素。若是不可能,返回 -1。數組
示例 1:編碼
輸入:A = [0,1,0], K = 1
輸出:2
解釋:先翻轉 A[0],而後翻轉 A[2]。code
示例 2:blog
輸入:A = [1,1,0], K = 2
輸出:-1
解釋:不管咱們怎樣翻轉大小爲 2 的子數組,咱們都不能使數組變爲 [1,1,1]。圖片
示例 3:ip
輸入: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]leetcode
提示:get
1 <= A.length <= 30000 1 <= K <= A.length
來源:力扣(LeetCode)it
int minKBitFlips(int* A, int ASize, int K){ }
題目要求就是對於一個已知的01組成的數組進行K長度的子數組的翻轉(0->1,1->0),求翻轉到最後全部元素都爲1的最少次數,若是不能達到這個目的就返回-1;
這一題應用到了不少的方法:好比貪心算法,差分,滑窗。
咱們所要翻轉的是一個長度爲K的小窗口,可翻轉,翻轉兩次等於沒翻。
從作到有判斷是否每一個元素都須要翻轉。
若是須要翻轉就記錄翻轉次數,記錄就是差分遍歷的首位(i)加,末位(i+k)減。最後再利用差分求累計翻轉次數;
若是須要翻轉,但剩餘元素長度已經不足K個,那麼就是沒法完成全置1的目標,返回-1便可。
這裏是對於差分數組的創建以及初始化,以及對最後須要返回的反轉次數ans的定義,對於revCnt就是算做咱們的差分數組的首位diff[i];
int diff[ASize + 1]; memset(diff, 0, sizeof(diff)); int ans = 0, revCnt = 0;
for (int i = 0; i < ASize; ++i) { }
revCnt += diff[i];
if ((A[i] + revCnt) % 2 == 0) { if (i + K > ASize) { return -1; } }
++ans; ++revCnt; --diff[i + K];
int minKBitFlips(int* A, int ASize, int K) { int diff[ASize + 1]; memset(diff, 0, sizeof(diff)); int ans = 0, revCnt = 0; for (int i = 0; i < ASize; ++i) { revCnt += diff[i]; if ((A[i] + revCnt) % 2 == 0) { if (i + K > ASize) { return -1; } ++ans; ++revCnt; --diff[i + K]; } } return ans; }