LeetCode 🔴 995. Minimum Number of K Consecutive Bit Flips
🔗 🔴 995. Minimum Number of K Consecutive Bit Flips 1835
tags: Weekly Contest 124
差分陣列(Difference Array)
前綴和(Prefix Sum)
滑動窗口(Sliding Window)
題意
給定一個二進位陣列 和一個整數 。
在每次操作中,可以從 中選擇一個長度為 的子陣列,同時將子陣列中的每個 改為 ,每個 改為 。
返回使得陣列中沒有 所需的最小操作次數。如果無法完成,請返回 。
子陣列(Subarray) 是指陣列的連續部分。
約束條件
思路
這題跟 3191. Minimum Operations to Make Binary Array Elements Equal to One I 很類似,只是該題中的 ,可以視為常數。在該題中,我們可以由前往後找到需要被翻轉的位置,並將大小為 的區間直接翻轉。
但在此題中這樣做的話,時間複雜度為 ,當 時,會超時。因此我們需要找到更好的方法。
方法一:差分陣列(Difference Array)
首先將直接翻轉改為 紀錄翻轉次數 ,因此翻轉次數為奇數的位置代表已經翻轉過,翻轉次數為偶數的位置代表未翻轉。若該位置為 且翻轉次數為偶數、或該位置為 且翻轉次數為奇數,則需要從當前位置開始翻轉 個元素。
在紀錄翻轉次數時,需要使用到區間加法,而逐位加法的時間複雜度為 ,因此需要找到更好的方法。為此可以使用 差分陣列(Difference Array) ,這是一個與 前綴和(Prefix Sum) 相對應的概念,可以在 的時間實現區間加法的功能,將區間 上的所有數 可以轉換成對差分陣列的 位置 , 位置 ,最後再對差分陣列做前綴和即可還原出原始陣列。差分陣列的具體介紹本處省略,可以自行參考相關資料。
從左到右遍歷陣列 ,當遇到需要翻轉的位置時,對差分陣列進行區間加法,並將翻轉次數加一。最後返回總共的翻轉次數即可,具體步驟如下:
- 令 表示當前位置的翻轉次數,對差分陣列求前綴和即可得到。
- 令 表示翻轉次數的差分陣列,對於每個位置 ,若 需要翻轉,則需要將 區間的翻轉次數加一,即對 加一,對 減一。
- 由於 只會在 位置用到,因此可以省略對 的加法操作,只需要對 加一即可。
- 在判斷是否需要翻轉時,可以由當前位置的翻轉次數 的奇偶性來判斷,若 ,則需要翻轉。
- 由於 已經被翻轉 次,因此當 且 是偶數,或 且 是奇數時,則需要翻轉。
- 若在需要翻轉時,若 ,則不足以翻轉以 為起點的 個元素,直接返回 。
- 最後返回 即可。
此外,由於我們在上述過程中只關注 和 陣列的奇偶性,因此可以將 操作改為 ,為方便理解,在 Python
範例程式碼中不做這樣的優化,可見 C++
範例程式碼。
複雜度分析
- 時間複雜度:。
- 空間複雜度:。
1 | class Solution: |
1 | class Solution { |
方法二:滑動窗口(Sliding Window)
根據方法一,當遍歷到位置 時,若 位置上發生了翻轉操作,則當前位置的翻轉次數 需要減一。從這個角度出發,可以不使用 陣列,而是跟據 位置的狀態來直接修改 ,也就是在加入右側的元素時,考慮左側的元素的狀態,這種方式和 滑動窗口(Sliding Window) 的思想相符。
為了得知 位置上是否發生了翻轉操作,需要使用一些標記方式。例如使用一個額外陣列來表示該位置的翻轉次數,但這樣會增加空間複雜度。由於 ,我們可以將 的範圍之外的數來表示該位置「是否翻轉過」。
- 若翻轉從位置 開始的子陣列,可以將 加 ,這樣當遍歷到位置 時,若有 ,則說明在位置 上發生了翻轉操作。
- 若需要還原原始陣列,只需要將 減 即可。
具體步驟如下:
- 令 表示總共的翻轉次數, 表示窗口內的翻轉次數,皆初始化為 。
- 接著遍歷 陣列,對於每個位置 :
- 當 時,需要檢查窗口左側的元素是否發生了翻轉操作,若是,則需要將 減一。
- 若 需要翻轉,即當 時,則需要標記從位置 開始的 個元素已經翻轉過,並將 加一。
- 透過將 加二來標記這個位置,代表從這個位置開始的 個元素被翻轉過。
- 若此時 ,則無法翻轉從位置 開始的 個元素,直接返回 。
- 最後返回 即可。
同樣的,由於我們在上述過程中只關注 的奇偶性,因此可以將 操作改為 ,為方便理解,在 Python
範例程式碼中不做這樣的優化,可見 C++
範例程式碼。
複雜度分析
- 時間複雜度:。
- 空間複雜度:。
1 | class Solution: |
1 | class Solution { |
類題
- 🟡 3191. Minimum Operations to Make Binary Array Elements Equal to One I _
- 🟡 3192. Minimum Operations to Make Binary Array Elements Equal to One II _
雖然是 Q3 ,但其實比該場的 Q2 還要簡單。
寫在最後
Cover photo is generated by @たろたろ, thanks for their work!
上禮拜雙周賽的題目進階升級版。