这是我参与11月更文挑战的第29天,活动详情查看:2021最后一次更文挑战。
题目描述:
697. 数组的度 - 力扣(LeetCode) (leetcode-cn.com)
给定一个非空且只包含非负数的整数数组 nums,数组的度的定义是指数组里任一元素出现频数的最大值。
你的任务是在 nums 中找到与 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.
示例二
输入: [1,2,2,3,1,4,2]
输出: 6
提示:
nums.length在1到 50,000 区间范围内。nums[i]是一个在 0 到 49,999 范围内的整数。
思路分析
哈希表
本题可以按照两部分求解:
- 先求原数组的度;
- 再求与原数组相同度的最短子数组。
首先,度的话,是指数组里任一元素出现频数的最大值,这个很好求解,可以利用哈希表来记录即可。
再次,就是我们需要找到相同度的最短子数组,这个乍看有点晦涩,其实很好理解,我们假设度为x,那么相同度的最小子数字即为第一个x到最后一个x。
AC代码
class Solution {
public int findShortestSubArray(int[] nums) {
//定义一个Map,Key为数组中的值,Value为一个数组,数组的第一个元素为Key出现的次数,第二个元素为Key第一次出现的位置,第三个元素为Key最后一次出现的位置。
Map<Integer,int[]> map = new HashMap<Integer,int[]>();
int n = nums.length;
//遍历数组,将每一个元素出现的次数、第一次出现的位置、最后一次出现的位置记录下来
for(int i = 0;i<n;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});
}
}
int maxNum = 0;
int minLen = 0;
//遍历Map,寻找出现最多次数的Key,若Key出现的次数相同,则选择长度较短的。
for(Map.Entry<Integer, int[]> entry : map.entrySet()){
int[] temp = entry.getValue();
if(temp[0] > maxNum){
maxNum = temp[0];
minLen = temp[2]-temp[1]+1;
}else if(temp[0] == maxNum){
if(minLen > temp[2]- temp[1]+1){
minLen = temp[2]-temp[1]+1;
}
}
}
return minLen;
}
}
总结
本题其实就是题目有点晦涩,其他还好。
另外这题其实滑动窗口也是非常不错的一个解法。
参考
数组的度 - 数组的度 - 力扣(LeetCode) (leetcode-cn.com)
详细分析题意与思路,简洁代码,看完必懂 - 数组的度 - 力扣(LeetCode) (leetcode-cn.com)
697. Degree of an Array 数组的度 - 数组的度 - 力扣(LeetCode) (leetcode-cn.com)