力扣995. K 連續位的最小翻轉次數-C語言實現-困難題

題目

傳送門算法

文本

在僅包含 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]綁定

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;
}

舉例流程

在這裏插入圖片描述

相關文章
相關標籤/搜索