题目描述:
给定一个非空且只包含非负数的整数数组 nums,数组的 度 的定义是指数组里任一元素出现频数的最大值。
你的任务是在 nums 中找到与 nums 拥有相同大小的度的最短连续子数组,返回其长度。
示例 1:
输入:nums = [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:
输入:nums = [1,2,2,3,1,4,2]
输出:6
解释:
数组的度是 3 ,因为元素 2 重复出现 3 次。
所以 [2,2,3,1,4,2] 是最短子数组,因此返回 6 。
提示:
nums.length 在 1 到 50,000 范围内。
nums[i] 是一个在 0 到 49,999 范围内的整数。
代码:
class Solution {
public:
int findShortestSubArray(vector<int>& nums) {
int n=nums.size(),max=0;
int minlen=n;
map<int,int> min_index,max_index,distance;
for(int i=0;i<n;i++){
if(min_index[nums[i]]==0){
min_index[nums[i]]=i+1; //+1避免第一个元素下标为0,记录了但检测不出来。
}
else continue;
}
for(int i=n-1;i>=0;i--){
if(max_index[nums[i]]==0)
max_index[nums[i]]=i+1;//+1避免第一个元素下标为0,记录了但检测不出来。
}
for(int i=0;i<n;i++){
distance[nums[i]]=max_index[nums[i]]-min_index[nums[i]]+1;
if(distance[nums[i]]==0)distance[nums[i]]=1; //只出现一次的数字,长度不为0,应为1
}
map<int,int> f;
for(int i=0;i<n;i++){
f[nums[i]]++;
if(f[nums[i]]>max)max=f[nums[i]];
}
for(int i=0;i<n;i++){
if(f[nums[i]]==max){
if(distance[nums[i]]<minlen)minlen=distance[nums[i]];
}
}
return minlen;
}
};
此题要求原数组中,包含出现次数最多的数字的最短连续子数组。
要想最短,只需要子数组的两头均为度数最大的数字(出现次数最多的数字),而左端和右端再没有其他数字。
连续是指求相同数字间的最远距离。
∴原问题转化为,求出重复出现次数最多且距离最远的数字间的长度。
例如,【1,2,2,3,1,3,6】中:
1出现2次,2出现2次,3出现2次,6出现1次;
1和1之间的最远距离为6,2和2间的距离为2,3和3之间的距离为3;
所以度数最大的最长连续子数组长度为6。
注意理解题意,转化问题。(”最大连续子数组长度“转化为相同数字间的最大距离)