题目来源
题目描述
class Solution {
public:
int findShortestSubArray(vector<int>& nums) {
}
};
题目解析
题意
- 数组的度:数组中各元素出现次数的最大值。比如1,2,2,3,1,4,2],数组中各元素出现的次数为:1出现2次,2出现3次,3出现1次,4出现1次,所以数组的度为3(也就是元素2出现的次数)
- 题目中要求与nums拥有相同大小的度的最短连续子数组的长度。比如对于示例二 [1,2,2,3,1,4,2],数组的度为 3,它的度为 3 的最短连续子数组是 [2,2,3,1,4,2] ,返回该子数组长度 6。
思路
本题可以按照两部分求解:
- 先求原数组的度
- 在求与原数组相同度的最短子数组
(1)求原数组的度
- 求数组的度,本质还是求各个元素的出现次数
- 我们可以用 哈希表计数,key 是元素,value 是该元素出现的次数。因此,所有 value 的最大值就是数组的度 degree
(2)在求与原数组相同度的最短子数组
- 要求的子数组的度与原数组相同度的相同,那么该子数组中也得有 degree个重复的元素。
- 比如对于示例二[1,2,2,3,1,4,2],出现次数最多的元素是 2,它的出现次数为 3, 所以数组的度为 3;我们要求的子数组得有 3 个 2 ,所以最短的子数组是 [2,2,3,1,4,2]。
- 可以看到,我们要求的最短子数组的起始和终止位置,由出现次数最多的元素 第一次和最后一次出现的位置决定
- 另外,需要注意的是出现次数最多的元素可能不止一个
- 比如示例一[1, 2, 2, 3, 1],数字 1 和数字 2 都出现了 2 次。
- 此时,我们必须分别对每个出现次数为 2 的元素(即数字 1 和数字 2 )都求一次包含2个它的最短子数组的长度(分别为5和2),最终对所有最短子数组长度取 minmin,得到结果为 2。
- 动画可以参考这里
class Solution {
public:
int findShortestSubArray(vector<int>& nums) {
std::unordered_map<int, int> left, right, counter;
int degree = 0;
for (int i = 0; i < nums.size(); ++i) {
int num = nums[i];
if(!left.count(num)){
left[num] = i;
}
right[num] = i;
counter[num]++;
degree = std::max(degree, counter[num]);
}
int res = nums.size();
for(auto kv : counter){
if(kv.second == degree){
res = std::min(res, right[kv.first] -left[kv.first] + 1);
}
}
return res;
}
};
类似题目
题目 | 思路 |
---|---|
leetcode:53. 子数组最大累加和 maximum-subarray | |
leetcode:697. 数组的度 degree-of-an-array |