LeetCode 1248. 統計「優美子數組」

1248. 統計「優美子數組」


題目來源:https://leetcode-cn.com/problems/count-number-of-nice-subarrays

題目


給你一個整數數組 nums 和一個整數 k。

如果某個 連續 子數組中恰好有 k 個奇數數字,我們就認爲這個子數組是「優美子數組」。

請返回這個數組中「優美子數組」的數目。

示例 1:

輸入:nums = [1,1,2,1,1], k = 3
輸出:2
解釋:包含 3 個奇數的子數組是 [1,1,2,1][1,2,1,1]

示例 2:

輸入:nums = [2,4,6], k = 1
輸出:0
解釋:數列中不包含任何奇數,所以不存在優美子數組。

示例 3:

輸入:nums = [2,2,2,1,2,2,1,2,2,2], k = 2
輸出:16

提示:

  • 1 <= nums.length <= 50000
  • 1 <= nums[i] <= 10^5
  • 1 <= k <= nums.length

解題思路


思路:雙指針(滑動窗口)

首先,理解題目的內容。

【如果某個連續子數組中恰好有 k 個奇數數字,我們就認爲這個子數組是「優美子數組」。】

這個就是【優美子數組】的定義,需要注意,子數組需連續,且有 k 個奇數數字。

那麼在這裏轉換下思路:也就是先找到連續 k 個奇數的子數組,那麼前後添加任意個偶數(注意只能是偶數,可以是 0 個),這裏都能構建【優美子數組】。

那麼具體的算法:

  • 定義雙指針,先移動右指針,擴大滑動窗口,使數組含有 k 個奇數;
  • 當滑動窗口包含 k 個奇數時,這個時候考慮構建【優美子數組】:
    • 計算滑動窗口第一個奇數左邊的偶數個數 left_even_count。如前面所述,這裏偶數可以是 0 個。所以計算出來的數目需加 1。
    • 計算滑動窗口第 k 個奇數右邊的偶數個數 right_even_count。與上面的一樣,計算數目需加 1。
  • 因爲題目要求,【優美子數組】爲含有連續包含 k 個奇數的子數組。那麼在最簡子數組的基礎上左右添加偶數元素同樣成立。那麼這裏的組合數爲 (left_even_count + 1) * (right_even_count + 1)

具體實現代碼如下。

代碼實現


class Solution:
    def numberOfSubarrays(self, nums: List[int], k: int) -> int:
        # 定義雙指針
        left, right = 0,  0
        # 統計奇數個數
        odd_count = 0
        # 返回結果
        ans = 0

        # 數組長度
        length = len(nums)

        while right < length:
            # 先移動右指針,統計奇數個數
            if nums[right] % 2 == 1:
                odd_count += 1
            
            right += 1

            # 當滑動窗口有 k 個奇數時,統計優美子數組個數
            if odd_count == k:
                # 這個時候向右邊擴大窗口,統計偶數個數,
                # 遇到奇數或者越界則停止
                sign = right
                while right < length and nums[right] % 2 == 0:
                    right += 1
                # 計算窗口右邊偶數個數
                right_even_count = right - sign
                
                # 統計窗口右邊的偶數個數後,
                # 現在統計窗口左邊的偶數個數
                left_event_count = 0
                while nums[left] % 2 == 0:
                    left_event_count += 1
                    left += 1
                
                # 現在計算組合數,添加到結果中
                # 注意:偶數個數可以爲 0 個,
                # 所以前面計算的左右偶數個數需加 1
                ans += (left_event_count + 1) * (right_even_count + 1)

                # 這個時候,數組後續可能還有其他的組合
                # left 在此時指向的是第一個奇數,所以向後移動一步
                left += 1
                odd_count -= 1

        return ans

實現結果


實現結果


以上就是使用雙指針(滑動窗口)的思路,運用固定含 k 個奇數的窗口,左右尋找偶數,進行組合的方法,用以解決《1248. 統計「優美子數組」》問題的主要內容。


歡迎關注微信公衆號《書所集錄》

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