给定一个非空且只包含非负数的整数数组 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
注意:
nums.length
在1到50,000区间范围内。nums[i]
是一个在0到49,999范围内的整数。
解析:
该题目需要计算出每个数字的度,用map比较容易计算;找到度最大的数字,然后将这些数字分别找到在数组中的第一个位置和最后一个位置,计算其长度,找出长度的最小值。
int findShortestSubArray(vector<int>& nums)
{
map<int, int>mNums;
for (int i = 0; i < nums.size(); i++)//用map计算度
{
mNums[nums[i]]++;
}
int m = 0;
//度的最大值m
for (map<int,int>::iterator iter=mNums.begin();iter!=mNums.end();iter++)
{
if (iter->second > m)
m = iter->second;
}
//如果最大度不大于1,则长度为1
if (m <= 1)
return 1;
int min = 50000;
//找到所有度为m的值的第一个和最后一个位置,计算长度,找出长度最小
for (map<int, int>::iterator iter = mNums.begin(); iter != mNums.end(); iter++)
{
if (iter->second == m)
{
int begin = 0, end = nums.size() - 1;
while (begin < end&&nums[begin] != iter->first)begin++;
while (begin < end&&nums[end] != iter->first)end--;
if ((end - begin + 1) < min)
min = end - begin + 1;
}
}
return min;
}
他山之石:
//map<int,vector<int>>,用于存储元素下标
int findShortestSubArray(vector<int>& nums)
{
int n = nums.size();
map<int,vector<int>> tmp;//vector记录出现的相同数的位置
for(int i=0;i<n;i++){
tmp[nums[i]].push_back(i);
}
int count = 0; //表征数组的度
int res = INT_MAX;
for(auto iter=tmp.begin();iter!=tmp.end();iter++){
int m = iter->second.size();//算一下数组的度
if(m>count){
count = m;
res = iter->second[m-1]-iter->second[0]+1;
}
if(m==count){
res=min(res,iter->second[m-1]-iter->second[0]+1);
}
}
return res;
}