Skip to content

Commit 70f1cd7

Browse files
committed
feat: add count distinct elements in window algorithm
1 parent 34079f0 commit 70f1cd7

2 files changed

Lines changed: 91 additions & 0 deletions

File tree

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package com.thealgorithms.slidingwindow;
2+
3+
import java.util.HashMap;
4+
import java.util.Map;
5+
6+
/**
7+
* Counts the number of distinct elements in every window of size k.
8+
*
9+
* @see <a href="https://www.geeksforgeeks.org/count-distinct-elements-in-every-window-of-size-k/">Reference</a>
10+
*/
11+
public final class CountDistinctElementsInWindow {
12+
13+
private CountDistinctElementsInWindow() {
14+
}
15+
16+
/**
17+
* Returns an array where each element is the count of distinct
18+
* elements in the corresponding window of size k.
19+
*
20+
* @param arr the input array
21+
* @param k the window size
22+
* @return array of distinct element counts per window
23+
*/
24+
public static int[] countDistinct(int[] arr, int k) {
25+
if (arr == null || arr.length == 0 || k <= 0 || k > arr.length) {
26+
throw new IllegalArgumentException("Invalid input");
27+
}
28+
29+
int n = arr.length;
30+
int[] result = new int[n - k + 1];
31+
Map<Integer, Integer> freqMap = new HashMap<>();
32+
33+
for (int i = 0; i < k; i++) {
34+
freqMap.merge(arr[i], 1, Integer::sum);
35+
}
36+
result[0] = freqMap.size();
37+
38+
for (int i = k; i < n; i++) {
39+
freqMap.merge(arr[i], 1, Integer::sum);
40+
41+
int outgoing = arr[i - k];
42+
freqMap.put(outgoing, freqMap.get(outgoing) - 1);
43+
if (freqMap.get(outgoing) == 0) {
44+
freqMap.remove(outgoing);
45+
}
46+
47+
result[i - k + 1] = freqMap.size();
48+
}
49+
50+
return result;
51+
}
52+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.thealgorithms.slidingwindow;
2+
3+
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
4+
import static org.junit.jupiter.api.Assertions.assertThrows;
5+
6+
import org.junit.jupiter.api.Test;
7+
8+
public class CountDistinctElementsInWindowTest {
9+
10+
@Test
11+
public void testBasicCase() {
12+
assertArrayEquals(new int[]{3, 2, 2, 2},
13+
CountDistinctElementsInWindow.countDistinct(new int[]{1, 2, 3, 2, 3}, 3));
14+
}
15+
16+
@Test
17+
public void testAllSame() {
18+
assertArrayEquals(new int[]{1, 1, 1},
19+
CountDistinctElementsInWindow.countDistinct(new int[]{2, 2, 2, 2}, 2));
20+
}
21+
22+
@Test
23+
public void testAllDistinct() {
24+
assertArrayEquals(new int[]{3, 3},
25+
CountDistinctElementsInWindow.countDistinct(new int[]{1, 2, 3, 4}, 3));
26+
}
27+
28+
@Test
29+
public void testWindowSizeEqualsArray() {
30+
assertArrayEquals(new int[]{4},
31+
CountDistinctElementsInWindow.countDistinct(new int[]{1, 2, 3, 4}, 4));
32+
}
33+
34+
@Test
35+
public void testInvalidInput() {
36+
assertThrows(IllegalArgumentException.class,
37+
() -> CountDistinctElementsInWindow.countDistinct(new int[]{}, 2));
38+
}
39+
}

0 commit comments

Comments
 (0)