classSolution: defnumberOfSubarrays(self, nums: List[int], k: int) -> int: n = len(nums) s = [0] * (n + 1) for i, x inenumerate(nums): s[i + 1] = s[i] + x % 2 ans = 0 for i inrange(n): ans += bisect_right(s, s[i] + k) - bisect_left(s, s[i] + k) return ans
1 2 3 4 5 6 7 8 9 10 11 12 13 14
classSolution { public: intnumberOfSubarrays(vector<int>& nums, int k){ int n = nums.size(); vector<int> s(n + 1); for (int i = 0; i < n; i++) s[i + 1] = s[i] + nums[i] % 2; int ans = 0; for (int i = 0; i < n; i++) { ans += upper_bound(s.begin(), s.end(), s[i] + k) - lower_bound(s.begin(), s.end(), s[i] + k); } return ans; } };
classSolution: defnumberOfSubarrays(self, nums: List[int], k: int) -> int: n = len(nums) ans = s = 0 cnt = [1] + [0] * n for x in nums: s += x & 1 if s >= k: ans += cnt[s - k] cnt[s] += 1 return ans
1 2 3 4 5 6 7 8 9 10 11 12 13 14
classSolution { public: intnumberOfSubarrays(vector<int>& nums, int k){ int n = nums.size(), ans = 0, s = 0; vector<int> cnt(n + 1); cnt[0] = 1; for (int x : nums) { s += x & 1; if (s >= k) ans += cnt[s - k]; cnt[s]++; } return ans; } };
方法三:滑動窗口(Sliding Window) + 數學(Math)
由於子陣列中必須要有 k 個奇數,因此我們可以考慮其最左邊的奇數位置和最右邊的奇數位置,左方能往左延伸長度即為左方的偶數個數 lcnt,右方能往右延伸長度即為右方的偶數個數 rcnt,根據 乘法原理 ,滿足條件的子陣列個數即為 (lcnt+1)×(rcnt+1)。
為此需要紀錄每個奇數的位置,令 odd 為所有奇數的位置,則 odd[i] 表示第 i 個奇數的位置。並透過枚舉最左邊的奇數位置來得出對應的右邊奇數位置,然後計算左右偶數個數即可得出該位置對答案的貢獻。
具體步驟如下:
初始化一個陣列 odd 來存儲所有奇數的位置,則第 i 個奇數的位置為 odd[i]。
為了後續計算方便,可以在 odd 陣列的前面加上 −1 和在後面加上 n。
初始化答案 ans=0。
遍歷 odd 陣列,對於每個位置 i,計算左右偶數個數 lcnt 和 rcnt。
最左邊的奇數位置是第 i 個奇數,則 lcnt=odd[i]−(odd[i−1] if i>0 else −1)−1。
最右邊的奇數位置是第 j=i+k−1 個奇數,則 rcnt=(odd[j+1] if j+1<len(odd) else n)−odd[j]−1。
classSolution: defnumberOfSubarrays(self, nums: List[int], k: int) -> int: n = len(nums) odd = [i for i, x inenumerate(nums) if x & 1] ans = 0 for i inrange(len(odd) - k + 1): # 枚舉最左邊的奇數 j = i + k - 1# 最右邊的奇數 lcnt = odd[i] - (odd[i-1] if i > 0else -1) - 1# 左邊的偶數個數 rcnt = (odd[j+1] if j + 1 < len(odd) else n) - odd[j] - 1# 右邊的偶數個數 ans += (lcnt + 1) * (rcnt + 1) return ans
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
classSolution { public: intnumberOfSubarrays(vector<int>& nums, int k){ int n = nums.size(), ans = 0; vector<int> odd; odd.push_back(-1); // dummy for (int i = 0; i < n; i++) if (nums[i] & 1) odd.push_back(i); odd.push_back(n); // dummy for (int i = 1; i + k < odd.size(); i++) { int j = i + k - 1; ans += (odd[i] - odd[i - 1]) * (odd[j + 1] - odd[j]); } return ans; } };
寫在最後
Cover photo is generated by @たろたろ, thanks for their work!