问题描述
小A拿到了一个长度为nn的数组,并且定义了一个连续子数组的“权值”为该子数组内不同元素的个数。现在,她想知道,权值分别为1,2,3,…,n1,2,3,…,n的子数组数量有多少个。
你需要根据给定的数组,输出一个包含nn个整数的数组,第ii个数表示权值为ii的子数组数量。
做题思路:
-
暴力枚举所有子数组:
- 我们需要找出数组
a中权值(即子数组内不同元素的个数)为从1到n的子数组数量。为了实现这个目标,一种直观的方法是通过两层循环来枚举所有可能的连续子数组。 - 外层循环控制子数组的起始位置
i,从数组的开头开始,逐步向后移动,直到数组的倒数第二个位置(因为内层循环还会从i往后延伸形成子数组)。 - 内层循环控制子数组的结束位置
j,从外层循环确定的起始位置i开始,一直到数组的末尾,这样就可以枚举出以i为起始位置的所有连续子数组。
- 我们需要找出数组
-
统计子数组内不同元素个数:
- 对于每一个枚举出来的子数组(由
i和j确定),我们需要统计其中不同元素的个数,也就是子数组的权值。 - 这里使用一个无序映射(
unordered_map)来实现。在每次内层循环迭代时,对于当前元素a[j],我们检查它在映射count中的出现次数。 - 如果
count[a[j]]等于0,说明这个元素是第一次在当前子数组中出现,那么就将不同元素的个数distinct加1。然后,无论是否是第一次出现,都要将该元素在映射中的出现次数加1,以记录它在子数组中的出现情况。
- 对于每一个枚举出来的子数组(由
-
记录权值对应的子数组数量:
- 在统计完每个子数组的不同元素个数(即权值)后,我们使用一个数组
c来记录权值为不同值时的子数组数量。 - 数组
c的下标表示权值,数组元素的值表示权值为该下标的子数组数量。所以,每当我们确定了一个子数组的权值distinct后,就将c[distinct]的值加1。
- 在统计完每个子数组的不同元素个数(即权值)后,我们使用一个数组
vector<int> solution(int n, vector<int>& a) {
vector<int> c(n + 1, 0);
for (int i = 0; i < n; ++i) {
unordered_map<int, int> count;
int distinct = 0;
for (int j = i; j < n; ++j) {
if (count[a[j]] == 0) {
distinct++;
}
count[a[j]]++;
c[distinct]++;
}
}
return vector<int>(c.begin() + 1, c.end());
}
在这段代码中,通过两层循环枚举了所有可能的连续子数组,并借助无序映射统计了每个子数组内不同元素的个数,最后将不同权值对应的子数组数量记录在数组 c 中并返回。整体时间复杂度相对较高,因为是通过暴力枚举的方式,大致为 ,其中 n 是数组 a 的长度。空间复杂度主要取决于无序映射 count 存储的不同元素的数量,在最坏情况下可能达到 。