LeetCode 995. K 連續位的最小翻轉次數(差分思想)

文章目錄

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阿明),一起加油、一起學習進步!
Michael阿明

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章