【LEETCODE】75、第1248題 統計「優美子數組」

package array.medium;

/**
 * @Auther: xiaof
 * @Date: 2020/4/21 10:48
 * @Description:1248. 統計「優美子數組」
 * 給你一個整數數組 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
 *
 * 來源:力扣(LeetCode)
 * 鏈接:https://leetcode-cn.com/problems/count-number-of-nice-subarrays
 * 著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。
 */
public class NumberOfSubarrays {

    public int solution(int[] nums, int k) {
        int i = 0, j = 0, ki = 0, res = 0;
        while (i < nums.length && j < nums.length) {
            //判斷範圍,判斷窗口邊緣是否是瞞住條件
            if (isOdd(nums[j])) {
                //如果j是奇數
                ki++;
            }
            //判斷窗口是否瞞住k個,並對窗口進行改變,要保證恰好有K個,多了少了都不行
            while ((j - i + 1) >= k && ki == k) {
                res++;
                //如果瞞住了,那麼從當前j到這個串的後續所有偶數都是符合的
                for (int x = j + 1; x < nums.length; ++x) {
                    if (!isOdd(nums[x])) {
                        res++;
                    } else break;
                }
//                res++;
                //然後判斷前面的窗口進行遞增
                if (isOdd(nums[i])) {
                    ki--;
                }
                i++;
            }
            ++j;
        }
        //去掉全集
        return res;
    }

    private boolean isOdd(int n) {
        //判斷是否是奇數
        if ((n & 1) == 0) {
            return false;
        } else {
            return true;
        }
    }


    public int numberOfSubarrays(int[] nums, int k) {
        if (nums == null || nums.length == 0 || nums.length < k) return 0;
        // 雙指針
        int left = 0, right = 0;
        int count = 0; // 連續子數組中奇數的個數
        int res = 0;
        int preEven = 0; // 記錄第一個奇數前面的偶數個數
        while (right < nums.length){
            // 連續子數組中奇數個數不夠
            if (count < k){
                if (nums[right] % 2 != 0) count++;
                right++; // 移動右側指針
            }
            // 連續子數組中奇數個數夠了,看第一個奇數前面有多少個偶數
            if (count == k) {
                preEven = 0;
                while (count == k){
                    res++;
                    if (nums[left] % 2 != 0) count--;
                    left++;
                    preEven++;
                }
            } else res += preEven; // 每次遇到 right 爲偶數的時候就進行累加 相當於區間前面偶數個數 * 後面偶數個數
        }
        return res;
    }

    public static void main(String[] args) {
        NumberOfSubarrays fuc = new NumberOfSubarrays();
        int nums1[] = {2,2,2,1,2,2,1,2,2,2}, k1 = 2;
        int nums2[] = {1,1,2,1,1}, k2 = 3;
        int nums3[] = {45627,50891,94884,11286,35337,46414,62029,20247,72789,89158,54203,79628,25920,16832,47469,80909}, k3 = 1;

        fuc.solution(nums3, k3);
//        fuc.numberOfSubarrays(nums2, k2);
    }
}

 

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