mirror of
https://github.com/TheAlgorithms/Java.git
synced 2026-03-13 08:40:43 +08:00
Add Count Nice Subarrays sliding using window algorithm (#7206)
* Add Count Nice Subarrays sliding window algorithm * Add detailed comments and reference to CountNiceSubarrays * Fix clang-format issues in CountNiceSubarrays * Added extra edge cases * changes made
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
package com.thealgorithms.slidingwindow;
|
||||
|
||||
/**
|
||||
* Counts the number of "nice subarrays".
|
||||
* A nice subarray is a contiguous subarray that contains exactly k odd numbers.
|
||||
*
|
||||
* This implementation uses the sliding window technique.
|
||||
*
|
||||
* Reference:
|
||||
* https://leetcode.com/problems/count-number-of-nice-subarrays/
|
||||
*
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*/
|
||||
public final class CountNiceSubarrays {
|
||||
|
||||
// Private constructor to prevent instantiation
|
||||
private CountNiceSubarrays() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the count of subarrays containing exactly k odd numbers.
|
||||
*
|
||||
* @param nums input array of integers
|
||||
* @param k number of odd elements required in the subarray
|
||||
* @return number of nice subarrays
|
||||
*/
|
||||
public static int countNiceSubarrays(int[] nums, int k) {
|
||||
|
||||
int n = nums.length;
|
||||
|
||||
// Left pointer of the sliding window
|
||||
int left = 0;
|
||||
|
||||
// Tracks number of odd elements in the current window
|
||||
int oddCount = 0;
|
||||
|
||||
// Final answer: total number of nice subarrays
|
||||
int result = 0;
|
||||
|
||||
/*
|
||||
* memo[i] stores how many valid starting positions exist
|
||||
* when the left pointer is at index i.
|
||||
*
|
||||
* This avoids recomputing the same values again.
|
||||
*/
|
||||
int[] memo = new int[n];
|
||||
|
||||
// Right pointer moves forward to expand the window
|
||||
for (int right = 0; right < n; right++) {
|
||||
|
||||
// If current element is odd, increment odd count
|
||||
if ((nums[right] & 1) == 1) {
|
||||
oddCount++;
|
||||
}
|
||||
|
||||
/*
|
||||
* If oddCount exceeds k, shrink the window from the left
|
||||
* until oddCount becomes valid again.
|
||||
*/
|
||||
if (oddCount > k) {
|
||||
left += memo[left];
|
||||
oddCount--;
|
||||
}
|
||||
|
||||
/*
|
||||
* When the window contains exactly k odd numbers,
|
||||
* count all possible valid subarrays starting at `left`.
|
||||
*/
|
||||
if (oddCount == k) {
|
||||
|
||||
/*
|
||||
* If this left index hasn't been processed before,
|
||||
* count how many consecutive even numbers follow it.
|
||||
*/
|
||||
if (memo[left] == 0) {
|
||||
int count = 0;
|
||||
int temp = left;
|
||||
|
||||
// Count consecutive even numbers
|
||||
while ((nums[temp] & 1) == 0) {
|
||||
count++;
|
||||
temp++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Number of valid subarrays starting at `left`
|
||||
* is (count of even numbers + 1)
|
||||
*/
|
||||
memo[left] = count + 1;
|
||||
}
|
||||
|
||||
// Add number of valid subarrays for this left position
|
||||
result += memo[left];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.thealgorithms.slidingwindow;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class CountNiceSubarraysTest {
|
||||
@Test
|
||||
void testExampleCase() {
|
||||
int[] nums = {1, 1, 2, 1, 1};
|
||||
assertEquals(2, CountNiceSubarrays.countNiceSubarrays(nums, 3));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAllEvenNumbers() {
|
||||
int[] nums = {2, 4, 6, 8};
|
||||
assertEquals(0, CountNiceSubarrays.countNiceSubarrays(nums, 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSingleOdd() {
|
||||
int[] nums = {1};
|
||||
assertEquals(1, CountNiceSubarrays.countNiceSubarrays(nums, 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMultipleChoices() {
|
||||
int[] nums = {2, 2, 1, 2, 2, 1, 2};
|
||||
assertEquals(6, CountNiceSubarrays.countNiceSubarrays(nums, 2));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTrailingEvenNumbers() {
|
||||
int[] nums = {1, 2, 2, 2};
|
||||
assertEquals(4, CountNiceSubarrays.countNiceSubarrays(nums, 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMultipleWindowShrinks() {
|
||||
int[] nums = {1, 1, 1, 1};
|
||||
assertEquals(3, CountNiceSubarrays.countNiceSubarrays(nums, 2));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEvensBetweenOdds() {
|
||||
int[] nums = {2, 1, 2, 1, 2};
|
||||
assertEquals(4, CountNiceSubarrays.countNiceSubarrays(nums, 2));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testShrinkWithTrailingEvens() {
|
||||
int[] nums = {2, 2, 1, 2, 2, 1, 2, 2};
|
||||
assertEquals(9, CountNiceSubarrays.countNiceSubarrays(nums, 2));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user