1. 程式人生 > 其它 >LeetCode 995 K連續位的最小翻轉次數 HERODING的LeetCode之路

LeetCode 995 K連續位的最小翻轉次數 HERODING的LeetCode之路

技術標籤:LeetCode演算法leetcodec++資料結構程式人生

在僅包含 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
著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。

解題思路:
這道題是通過參考官方思路寫出來的,當然官方思路不太容易理解,這裡我用我自己理解的方式解釋給大家,整體的思路就是貪心,當前是1不翻轉,是0就翻轉,一直到最後,如果在最後K個數範圍內還有0,那沒辦法了,直接返回-1,每次翻轉前要統計已經翻轉的次數,這個次數並不是累加的,舉個例子,如果k是2,第一個數是0,第二個數是1,那麼首先翻轉第一個K長度陣列,變成了[1 ,0],這個時候統計翻轉次數的reverse陣列要更新,將 0 + 2 位置的值-1,意思是從這開始沒有翻轉,相對於前一個k範圍陣列少翻轉一次,計算到這時要減去1,每翻轉一次就要更新當前翻轉次數,即 cur++,所以總而言之,i + k 位置相當於標記,指明從這開始少翻轉 reverse[i + k] 次。

當然為了提高記憶體執行效率,可以不用reverse陣列,那如何標記呢?這就要利用到題中所給的A陣列,因為陣列中值的範圍為0或者1,所以只要把A陣列中對應位置的值更新到大於1即可作為標記,詳細思路見題解,程式碼如下:

class Solution {
public:
    int minKBitFlips(vector<int> &A, int K) {
        int len = A.size();
        int count = 0;
        int cur = 0;
        // 翻轉次數
        vector<int> reverse(len + 1);
        for(int i = 0; i < len; i ++) {
            // 統計當前翻轉次數
            cur += reverse[i];
            // 說明翻轉過了
            if((cur + A[i]) % 2 == 0) {
                // 超過範圍
                if(i + K > len) {
                    return -1;
                }
                count ++;
                cur ++;
                reverse[i + K] --;
            }
        }
        return count;
    }
};




/*作者:heroding
連結:https://leetcode-cn.com/problems/minimum-number-of-k-consecutive-bit-flips/solution/zui-xiang-xi-cti-jie-by-heroding-1c4p/
來源:力扣(LeetCode)
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。*/