|
1 | 1 | package com.thealgorithms.slidingwindow; |
2 | 2 |
|
3 | | -public class CountNiceSubarrays { |
| 3 | +/** |
| 4 | + * Counts the number of "nice subarrays". |
| 5 | + * A nice subarray is a contiguous subarray that contains exactly k odd numbers. |
| 6 | + * |
| 7 | + * This implementation uses the sliding window technique. |
| 8 | + * |
| 9 | + * Reference: |
| 10 | + * https://leetcode.com/problems/count-number-of-nice-subarrays/ |
| 11 | + * |
| 12 | + * Time Complexity: O(n) |
| 13 | + * Space Complexity: O(n) |
| 14 | + */ |
| 15 | +public final class CountNiceSubarrays { |
| 16 | + |
| 17 | + // Private constructor to prevent instantiation |
4 | 18 | private CountNiceSubarrays() { |
5 | 19 | } |
6 | 20 |
|
| 21 | + /** |
| 22 | + * Returns the count of subarrays containing exactly k odd numbers. |
| 23 | + * |
| 24 | + * @param nums input array of integers |
| 25 | + * @param k number of odd elements required in the subarray |
| 26 | + * @return number of nice subarrays |
| 27 | + */ |
7 | 28 | public static int countNiceSubarrays(int[] nums, int k) { |
| 29 | + |
8 | 30 | int n = nums.length; |
| 31 | + |
| 32 | + // Left pointer of the sliding window |
9 | 33 | int left = 0; |
| 34 | + |
| 35 | + // Tracks number of odd elements in the current window |
10 | 36 | int oddCount = 0; |
| 37 | + |
| 38 | + // Final answer: total number of nice subarrays |
11 | 39 | int result = 0; |
| 40 | + |
| 41 | + /* |
| 42 | + * memo[i] stores how many valid starting positions exist |
| 43 | + * when the left pointer is at index i. |
| 44 | + * |
| 45 | + * This avoids recomputing the same values again. |
| 46 | + */ |
12 | 47 | int[] memo = new int[n]; |
13 | 48 |
|
| 49 | + // Right pointer moves forward to expand the window |
14 | 50 | for (int right = 0; right < n; right++) { |
| 51 | + |
| 52 | + // If current element is odd, increment odd count |
15 | 53 | if ((nums[right] & 1) == 1) { |
16 | 54 | oddCount++; |
17 | 55 | } |
18 | 56 |
|
| 57 | + /* |
| 58 | + * If oddCount exceeds k, shrink the window from the left |
| 59 | + * until oddCount becomes valid again. |
| 60 | + */ |
19 | 61 | if (oddCount > k) { |
20 | 62 | left += memo[left]; |
21 | 63 | oddCount--; |
22 | 64 | } |
23 | 65 |
|
| 66 | + /* |
| 67 | + * When the window contains exactly k odd numbers, |
| 68 | + * count all possible valid subarrays starting at `left`. |
| 69 | + */ |
24 | 70 | if (oddCount == k) { |
| 71 | + |
| 72 | + /* |
| 73 | + * If this left index hasn't been processed before, |
| 74 | + * count how many consecutive even numbers follow it. |
| 75 | + */ |
25 | 76 | if (memo[left] == 0) { |
26 | 77 | int count = 0; |
27 | 78 | int temp = left; |
| 79 | + |
| 80 | + // Count consecutive even numbers |
28 | 81 | while ((nums[temp] & 1) == 0) { |
29 | 82 | count++; |
30 | 83 | temp++; |
31 | 84 | } |
| 85 | + |
| 86 | + /* |
| 87 | + * Number of valid subarrays starting at `left` |
| 88 | + * is (count of even numbers + 1) |
| 89 | + */ |
32 | 90 | memo[left] = count + 1; |
33 | 91 | } |
| 92 | + |
| 93 | + // Add number of valid subarrays for this left position |
34 | 94 | result += memo[left]; |
35 | 95 | } |
36 | 96 | } |
|
0 commit comments