题目详情
Given a non-empty array of non-negative integers nums, the degree of this array is defined as the maximum frequency of any one of its elements.
Your task is to find the smallest possible length of a (contiguous) subarray of nums, that has the same degree as nums.
输入一个正整数数组,这个数组的“度”就是数组中任意元素出现的最大次数。而我们要找出这个数组的一个子数组,满足“度”等于整个数组的“度”的同时,保证子数组的长度最小,返回这个最小的长度。Example 1:
Input: [1, 2, 2, 3, 1]
Output: 2
Explanation:
输入数组的度为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。
Example 2:
Input: [1,2,2,3,1,4,2]
Output: 6
想法
- 想尽量减少遍历的次数,因此在第一趟遍历中我们即保存了所有元素出现的次数,也保存了每个元素出现的范围。
- 因为涉及到对元素出现次数的计数,因此我们采用HashMap来实现。一个HashMap保存元素的值和出现的次数。另一个Hashmap保存元素的值和元素出现的范围,用int[] numRange数组表示,numRange[0]表示第一次出现的位置,numRange[1]表示最后出现的位置。
- 最后遍历HashMap,获取满足“度”相等的最小子数组长度。
解法
public int findShortestSubArray(int[] nums) {
int minLength = nums.length;
int degree = 0;
HashMap<Integer, Integer> count = new HashMap<Integer,Integer>();
HashMap<Integer,Integer[]> index = new HashMap<Integer,Integer[]>();
for(int i=0;i<nums.length;i++){
count.put(nums[i], count.getOrDefault(nums[i], 0) + 1);
degree = Math.max(degree, count.get(nums[i]));
if(index.get(nums[i]) == null){
index.put(nums[i],new Integer[2]);
}
Integer[] numRange = index.get(nums[i]);
if(numRange[0] == null)numRange[0] = i;
numRange[1] = i;
}
for(Map.Entry<Integer, Integer> entry : count.entrySet()){
if(entry.getValue() != degree){
continue;
}
Integer[] range = index.get(entry.getKey());
minLength = Math.min(minLength, range[1]-range[0]+1);
}
return minLength;
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。