You are given an array of integers nums
and an integer k
. Your task is to find, for every contiguous subarray of length k
in nums
, how many distinct numbers are present in that subarray.
Return an array result
where result[i]
is the number of distinct integers in the subarray nums[i:i+k]
.
k
.
k
(from index 0
to len(nums)-k
).
Example:
Input: nums = [1,2,3,2,2,1,3]
, k = 3
Output: [3,2,2,2,2]
At first glance, the problem looks like a sliding window problem. For each window of size k
, we need to count how many different numbers are present. The brute-force way would be to, for each subarray, collect its elements and count the number of unique values (perhaps by converting to a set).
However, this brute-force approach would be slow for large arrays because it repeats a lot of work. Instead, we can optimize by noticing that as we "slide" the window to the right by one, only one number leaves the window and one new number enters. If we can efficiently keep track of the counts of each number in the current window, we can update the number of distinct elements in constant time per step.
This is a classic use-case for a hash map (dictionary): we can store the frequency of each number in the current window. When a number leaves, we decrement its count (and if its count drops to zero, it is no longer present). When a new number enters, we increment its count. The number of keys in the map with count > 0 gives us the number of distinct elements.
Let's break down the optimized approach step by step:
k
elements, add each to the hash map and track the number of unique keys (distinct numbers).
This approach ensures that each element is added and removed from the hash map at most once per window, making the algorithm efficient.
Let's use the example nums = [1,2,3,2,2,1,3]
and k = 3
.
k
, create a set of its elements to count distinct numbers. There are n-k+1
windows, and each set operation takes up to O(k)
time, so total time is O((n-k+1) * k)
.
O(1)
(on average). Each element is added and removed at most once, so total time is O(n)
.
k
different numbers (if all are unique in a window), so space is O(k)
.
The problem of finding the number of distinct numbers in each sliding window of size k
can be solved efficiently using a sliding window and a hash map to keep track of element counts. By updating the counts as we move the window, we avoid redundant work and achieve linear time complexity. This approach is both elegant and practical, making it suitable for large input sizes.
from collections import defaultdict
def distinctNumbers(nums, k):
result = []
count = defaultdict(int)
distinct = 0
for i in range(len(nums)):
count[nums[i]] += 1
if count[nums[i]] == 1:
distinct += 1
if i >= k:
count[nums[i - k]] -= 1
if count[nums[i - k]] == 0:
distinct -= 1
if i >= k - 1:
result.append(distinct)
return result
#include <vector>
#include <unordered_map>
using namespace std;
vector<int> distinctNumbers(vector<int>& nums, int k) {
vector<int> result;
unordered_map<int, int> count;
int distinct = 0;
for (int i = 0; i < nums.size(); ++i) {
count[nums[i]]++;
if (count[nums[i]] == 1) distinct++;
if (i >= k) {
count[nums[i - k]]--;
if (count[nums[i - k]] == 0) distinct--;
}
if (i >= k - 1) result.push_back(distinct);
}
return result;
}
import java.util.*;
public class Solution {
public List<Integer> distinctNumbers(int[] nums, int k) {
List<Integer> result = new ArrayList<>();
Map<Integer, Integer> count = new HashMap<>();
int distinct = 0;
for (int i = 0; i < nums.length; ++i) {
count.put(nums[i], count.getOrDefault(nums[i], 0) + 1);
if (count.get(nums[i]) == 1) distinct++;
if (i >= k) {
count.put(nums[i - k], count.get(nums[i - k]) - 1);
if (count.get(nums[i - k]) == 0) distinct--;
}
if (i >= k - 1) result.add(distinct);
}
return result;
}
}
function distinctNumbers(nums, k) {
let result = [];
let count = new Map();
let distinct = 0;
for (let i = 0; i < nums.length; ++i) {
count.set(nums[i], (count.get(nums[i]) || 0) + 1);
if (count.get(nums[i]) === 1) distinct++;
if (i >= k) {
count.set(nums[i - k], count.get(nums[i - k]) - 1);
if (count.get(nums[i - k]) === 0) distinct--;
}
if (i >= k - 1) result.push(distinct);
}
return result;
}