LeetCode.697 数组的度

317 阅读2分钟

这是我参与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)