给定一个非空且只包含非负数的整数数组 nums, 数组的度的定义是指数组里任一元素出现频数的最大值。
你的任务是找到与 nums 拥有相同大小的度的最短连续子数组,返回其长度。
示例 1:
输入: [1, 2, 2, 3, 1]
输出: 2
解释:
输入数组的度是2,因为元素1和2的出现频数最大,均为2.
连续子数组里面拥有相同度的有如下所示:
[1, 2, 2, 3, 1], [1, 2, 2, 3], [2, 2, 3, 1], [1, 2, 2], [2, 2, 3], [2, 2]
最短连续子数组[2, 2]的长度为2,所以返回2.
示例 2:
输入: [1,2,2,3,1,4,2]
输出: 6
解:
他有一个最大的特点就是相同度最小长度的数组的首尾都是那个高频数!
方法:
1.先建立一个二元map容器
2.然后把数组中的元素依次存到这个容器里面,怎么存呢?第一部分存元素值,第二部分存元素的位置!
3.定义四个变量,分别存储元素的个数(也就是元素的度),数组的度,题目所求的最小度的长度, 以及一个临时变量
4.接下来开始对map进行遍历:
(1)先把第二个容器的大小,也就是该元素的个数,也就是元素的度拿出来,保存到元素度的变量里面。
(2)让该度和数组度进行比较,如果该度偏大就后期把他给数组度。(因为数组的度就是最大的元素的度)
(3)要这个度偏大,计算出它的长度保存在临时变量里(因为它有可能就是题目要求的最小长度)
(4)因为要求出最小的长度,所以当找出数组度之后,要从和数组度相等的元素里面挑出长度最小的。——你的任务是找到与 nums 拥有相同大小的度的最短连续子数组,返回其长度。
也就是如果元素的度等于数组的度,
(5)temp_len里面保存永远是当前的长度,当元素度和数组度相等的时候,将当前的长度和上一个也是数组度的元素度拿出来进行比较,看谁的长度短就把谁放进去。
int findShortestSubArray(vector<int>& nums) {
// 1. 利用 map 确定每个元素的度 (相同元素的所有索引)
//下面就是定义一个无序的map容器
unordered_map<int, vector<int>> degree_map;
// map 的 second 是 vector,所以用 push_back
//degree_map就是上面定义的容器
for (int i = 0; i < nums.size(); i++)
//数组数是几,就在map的第几个位置插入i
//map两个元素,push_back是给第二个元素插入
//map第一个值是数组的元素,第二个容器里存着这个数在数组中的哪些位置
degree_map[nums[i]].push_back(i);
// 每个元素的度
int n_degree = 0;
// 数组的度
int nums_degree = 0;
// 与数组度数相同的最短子数组的长度
int min_len = 0;
int tmp_len = 0;
// 2. 求跟原数组的度相同的最短子数组的长度
for (auto n : degree_map) {
// 3. 求每个元素 n 的度
//这样就求出了每个元素总共有几个
//数组的度的定义是指数组里任一元素出现频数的最大值。
n_degree = n.second.size();//注意写法
//如果该元素的度 > 数组中的度
//求出该元素的长度,并在后面把这个度赋给数组度
//!注意括号的范围!
if (n_degree >= nums_degree) {
// 4. 求每个子数组的长度
//该元素的最后一个位置 — 该元素第一个的位置 +1
//就得出来它的长度
tmp_len = n.second[n_degree - 1] - n.second[0] + 1;
//如果两个度相等,就看谁的长度最小
//!注意双等号!
if (n_degree == nums_degree) {
// 5. 找到度数相同子数组,每次取最小值
min_len = min(min_len, tmp_len);
} else {
// 这是 degree > nums_degree 的情况
// 求数组最大的度
nums_degree = n_degree;
// 更新子数组的长度
min_len = tmp_len;
}
}
}
return min_len;
}