题目定义:
给定一个非空且只包含非负数的整数数组 nums,数组的度的定义是指数组里任一元素出现频数的最大值。
你的任务是在 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来说,数组根据元素进行分组的数字为:[1,2,3],数字的出现次数为:[2,2,1],所以数组的度就为2,也就是数字 1 和 2 出现的系数
- 包含数组的度的最短子数组:题目要求的是与nums拥有相同数组的度的子数组,并且长度最短,根据示例1,包含数组的度的子数组有:[1, 2, 2, 3, 1], [1, 2, 2, 3], [2, 2, 3, 1], [1, 2, 2], [2, 2, 3], [2, 2],长度最短的子数组为:[2,2],所以返回最短子数组的长度:2
方式一(暴力破解):
class Solution {
private Map<Integer, Integer> map = new HashMap<>();
private int max = 0;
public int findShortestSubArray(int[] nums) {
int res = Integer.MAX_VALUE;
getMap(nums);
List<Integer> list = getMax();
for (Integer num : list) {
// right - left + 1 表示包含数组的度的子数组长度
//count 记录当前子数组中出现了被统计数字的次数
int left = -1, right = 0, count = 0;
while (right < nums.length) {
if (nums[right] == num) {
if(left == -1)
left = right;
count++;
}
//若出现次数等于数组的度,则计算子数组的大小
if (count == max) {
res = Math.min(res, right - left + 1);
break;
}
right++;
}
}
return res;
}
//根据哈希表获取出现次数最多的数字
//max 记录数组的度
private List<Integer> getMax() {
max = map.values().stream().max(Comparator.naturalOrder()).orElse(0);
return map.entrySet().stream()
.filter(e -> e.getValue() == max)
.map(Map.Entry::getKey)
.collect(Collectors.toList());
}
//哈希表统计每个数字出现的次数
private void getMap(int[] nums) {
for (int num : nums) {
map.put(num, map.getOrDefault(num, 0) + 1);
}
}
}
方式二(哈希表记录当前数字的次数,
第一次出现当前数字的下标,最后一次出现次数的下标):
/*
在实际代码中,我们使用哈希表实现该功能,每一个数映射到一个长度为 33 的数组,
数组中的三个元素分别代表这个数出现的次数、这个数在原数组中第一次出现的位置
和这个数在原数组中最后一次出现的位置。当我们记录完所有信息后,我们需要遍历该哈希表,
找到元素出现次数最多,且前后位置差最小的数
*/
class Solution {
private Map<Integer,int[]> map = new HashMap<>();
public int findShortestSubArray(int[] nums) {
getMap(nums);
int count = 0,res = 0;
for(Map.Entry<Integer,int[]> entry : map.entrySet()){
int[] array = entry.getValue();
if(count < array[0]){
count = array[0];
res = array[2] - array[1] + 1;
}else if(count == array[0]){
res = Math.min(res,array[2] - array[1] + 1);
}
}
return res;
}
private void getMap(int[] nums){
for(int i = 0; i < nums.length;i++){
if(map.containsKey(nums[i])){
map.get(nums[i])[0]++;
map.get(nums[i])[2] = i;
}else{
map.put(nums[i],new int[]{1,i,i});
}
}
}
}
参考:
https://leetcode-cn.com/problems/degree-of-an-array/solution/shu-zu-de-du-by-leetcode-solution-ig97/