Count Distinct Elements In Every Window of Size K
Given an array arr[] of size n and an integer k, return the count of distinct numbers in all windows of size k.
Examples:
Input: arr[] = [1, 2, 1, 3, 4, 2, 3], k = 4
Output: [3, 4, 4, 3]
Explanation: First window is [1, 2, 1, 3], count of distinct numbers is 3.
Second window is [2, 1, 3, 4] count of distinct numbers is 4.
Third window is [1, 3, 4, 2] count of distinct numbers is 4.
Fourth window is [3, 4, 2, 3] count of distinct numbers is 3.Input: arr[] = [4, 1, 1], k = 2
Output: [2, 1]
Explanation: First window is [4, 1], count of distinct numbers is 2.
Second window is [1, 1], count of distinct numbers is 1.
Table of Content
[Naive Approach] Traversing all windows of size k - O(n * k) Time and O(1) Space
Traverse the given array considering every window of size k in it and keeping a count on the distinct elements of the window.
// C++ program to count distinct elements in every window
// of size k by traversing all windows of size k
#include <iostream>
#include <vector>
#include <unordered_set>
using namespace std;
vector<int> countDistinct(vector<int> &arr, int k) {
int n = arr.size();
vector<int> res;
// Iterate over every window
for (int i = 0; i <= n - k; i++) {
// Hash Set to count unique elements
unordered_set<int> st;
for(int j = i; j < i + k; j++)
st.insert(arr[j]);
// Size of set denotes the number of unique elements
// in the window
res.push_back(st.size());
}
return res;
}
int main() {
vector<int> arr = {1, 2, 1, 3, 4, 2, 3};
int k = 4;
vector<int> res = countDistinct(arr, k);
for(int ele: res)
cout << ele << " ";
return 0;
}
// Java program to count distinct elements in every window
// of size k by traversing all windows of size k
import java.util.*;
class GfG {
static ArrayList<Integer> countDistinct(int[] arr, int k) {
int n = arr.length;
ArrayList<Integer> res = new ArrayList<>();
// Iterate over every window
for (int i = 0; i <= n - k; i++) {
// Hash Set to count unique elements
HashSet<Integer> st = new HashSet<>();
for(int j = i; j < i + k; j++)
st.add(arr[j]);
// Size of set denotes the number of unique elements
// in the window
res.add(st.size());
}
return res;
}
public static void main(String[] args) {
int[] arr = {1, 2, 1, 3, 4, 2, 3};
int k = 4;
ArrayList<Integer> res = countDistinct(arr, k);
for(int ele: res)
System.out.print(ele + " ");
}
}
# Python program to count distinct elements in every window
# of size k by traversing all windows of size k
def countDistinct(arr, k):
n = len(arr)
res = []
# Iterate over every window
for i in range(n - k + 1):
# Hash Set to count unique elements
st = set()
for j in range(i, i + k):
st.add(arr[j])
# Size of set denotes the number of unique elements
# in the window
res.append(len(st))
return res
if __name__ == "__main__":
arr = [1, 2, 1, 3, 4, 2, 3]
k = 4
res = countDistinct(arr, k)
for ele in res:
print(ele, end=" ")
// C# program to count distinct elements in every window
// of size k by traversing all windows of size k
using System;
using System.Collections.Generic;
class GfG {
static List<int> countDistinct(int[] arr, int k) {
int n = arr.Length;
List<int> res = new List<int>();
// Iterate over every window
for (int i = 0; i <= n - k; i++) {
// Hash Set to count unique elements
HashSet<int> st = new HashSet<int>();
for (int j = i; j < i + k; j++)
st.Add(arr[j]);
// Size of set denotes the number of unique elements
// in the window
res.Add(st.Count);
}
return res;
}
static void Main() {
int[] arr = {1, 2, 1, 3, 4, 2, 3};
int k = 4;
List<int> res = countDistinct(arr, k);
foreach (int ele in res)
Console.Write(ele + " ");
}
}
// JavaScript program to count distinct elements in every window
// of size k by traversing all windows of size k
function countDistinct(arr, k) {
let n = arr.length;
let res = [];
// Iterate over every window
for (let i = 0; i <= n - k; i++) {
// Hash Set to count unique elements
let st = new Set();
for (let j = i; j < i + k; j++)
st.add(arr[j]);
// Size of set denotes the number of unique elements
// in the window
res.push(st.size);
}
return res;
}
// Driver Code
let arr = [1, 2, 1, 3, 4, 2, 3];
let k = 4;
let res = countDistinct(arr, k);
console.log(res.join(' '));
Output
3 4 4 3
Time Complexity: O(n * k)
Auxiliary Space: O(1)
[Expected Approach] Sliding Window Technique - O(n) Time and O(k) Space
The idea is to use Sliding Window Technique and count the number of distinct element in the current window using the count of previous window. Maintain a hash map or dictionary to store the frequency of elements of the current window and the count of distinct elements in the window will be equal to the size of the hash map.
Store the frequency of first k elements in the hash map. Now start iterating from index = k,
- increase the frequency of arr[k] in the hash map.
- decrease the frequency of arr[i - k] in the hash map. If frequency of arr[i - k] becomes 0, remove arr[i] from the hash map.
- insert size of hash map into the resultant array.
// C++ program to count distinct elements in every window
// of size k by traversing all windows of size k
#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;
vector<int> countDistinct(vector<int> &arr, int k) {
int n = arr.size();
vector<int> res;
unordered_map<int, int> freq;
// Store the frequency of elements of first window
for(int i = 0; i < k; i++)
freq[arr[i]] += 1;
// Store the count of distinct element of first window
res.push_back(freq.size());
for(int i = k; i < n; i++) {
freq[arr[i]] += 1;
freq[arr[i - k]] -= 1;
// If the frequency of arr[i - k] becomes 0, remove
// it from hash map
if(freq[arr[i - k]] == 0)
freq.erase(arr[i - k]);
res.push_back(freq.size());
}
return res;
}
int main() {
vector<int> arr = {1, 2, 1, 3, 4, 2, 3};
int k = 4;
vector<int> res = countDistinct(arr, k);
for(int ele: res)
cout << ele << " ";
return 0;
}
// Java program to count distinct elements in every window
// of size k by traversing all windows of size k
import java.util.*;
class GfG {
// Function to count distinct elements in every window of size k
static List<Integer> countDistinct(int[] arr, int k) {
int n = arr.length;
ArrayList<Integer> res = new ArrayList<>();
Map<Integer, Integer> freq = new HashMap<>();
// Store the frequency of elements of the first window
for (int i = 0; i < k; i++) {
freq.put(arr[i], freq.getOrDefault(arr[i], 0) + 1);
}
// Store the count of distinct elements of the first window
res.add(freq.size());
for (int i = k; i < n; i++) {
freq.put(arr[i], freq.getOrDefault(arr[i], 0) + 1);
freq.put(arr[i - k], freq.get(arr[i - k]) - 1);
// If the frequency of arr[i - k] becomes 0,
// remove it from the hash map
if (freq.get(arr[i - k]) == 0) {
freq.remove(arr[i - k]);
}
res.add(freq.size());
}
return res;
}
public static void main(String[] args) {
int[] arr = {1, 2, 1, 3, 4, 2, 3};
int k = 4;
List<Integer> res = countDistinct(arr, k);
for (int ele : res) {
System.out.print(ele + " ");
}
}
}
# Python program to count distinct elements in every window
# of size k by traversing all windows of size k
from collections import defaultdict
# Function to count distinct elements in every window of size k
def countDistinct(arr, k):
n = len(arr)
res = []
freq = defaultdict(int)
# Store the frequency of elements of the first window
for i in range(k):
freq[arr[i]] += 1
# Store the count of distinct elements of the first window
res.append(len(freq))
for i in range(k, n):
freq[arr[i]] += 1
freq[arr[i - k]] -= 1
# If the frequency of arr[i - k] becomes 0, remove it from the hash map
if freq[arr[i - k]] == 0:
del freq[arr[i - k]]
res.append(len(freq))
return res
if __name__=='__main__':
arr = [1, 2, 1, 3, 4, 2, 3]
k = 4
res = countDistinct(arr, k)
print(*res)
// C# program to count distinct elements in every window
// of size k by traversing all windows of size k
using System;
using System.Collections.Generic;
class GfG {
// Function to count distinct elements in every window of size k
static List<int> CountDistinct(int[] arr, int k) {
int n = arr.Length;
List<int> res = new List<int>();
Dictionary<int, int> freq = new Dictionary<int, int>();
// Store the frequency of elements of the first window
for (int i = 0; i < k; i++) {
if (freq.ContainsKey(arr[i]))
freq[arr[i]] += 1;
else
freq[arr[i]] = 1;
}
// Store the count of distinct elements of the first window
res.Add(freq.Count);
for (int i = k; i < n; i++) {
// Add the new element to the frequency map
if (freq.ContainsKey(arr[i]))
freq[arr[i]] += 1;
else
freq[arr[i]] = 1;
// Remove the element that is sliding out of the window
freq[arr[i - k]] -= 1;
// If the frequency of arr[i - k] becomes 0, remove it from the dictionary
if (freq[arr[i - k]] == 0)
freq.Remove(arr[i - k]);
// Store the count of distinct elements in the current window
res.Add(freq.Count);
}
return res;
}
static void Main(string[] args) {
int[] arr = { 1, 2, 1, 3, 4, 2, 3 };
int k = 4;
List<int> res = CountDistinct(arr, k);
foreach (int ele in res) {
Console.Write(ele + " ");
}
}
}
// JavaScript program to count distinct elements in every
// window of size k by traversing all windows of size k
function countDistinct(arr, k) {
let n = arr.length;
let res = [];
let freq = new Map();
// Store the frequency of elements of the first window
for (let i = 0; i < k; i++) {
freq.set(arr[i], (freq.get(arr[i]) || 0) + 1);
}
// Store the count of distinct elements of the first window
res.push(freq.size);
for (let i = k; i < n; i++) {
// Add the new element to the frequency map
freq.set(arr[i], (freq.get(arr[i]) || 0) + 1);
// Remove the element that is sliding out of the window
freq.set(arr[i - k], freq.get(arr[i - k]) - 1);
// If the frequency of arr[i - k] becomes 0, remove it from the map
if (freq.get(arr[i - k]) === 0) {
freq.delete(arr[i - k]);
}
// Store the count of distinct elements in the current window
res.push(freq.size);
}
return res;
}
// Driver code
let arr = [1, 2, 1, 3, 4, 2, 3];
let k = 4;
let res = countDistinct(arr, k);
console.log(res.join(" "));
Output
3 4 4 3
Time complexity: O(n), where n is the size of the input array.
Auxiliary Space: O(k), as the size of the hash map or dictionary can be at most k.
Working:
Below is the illustration of finding count of distinct elements in every window of size 4: