2

题目详情

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;
    }
    

soleil阿璐
350 声望45 粉丝

stay real ~