zoukankan      html  css  js  c++  java
  • Leetcode 697 数组的度

    题目定义:

    给定一个非空且只包含非负数的整数数组 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/

  • 相关阅读:
    idea 中使用 svn
    [剑指offer] 40. 数组中只出现一次的数字
    [剑指offer] 39. 平衡二叉树
    [剑指offer] 38. 二叉树的深度
    [剑指offer] 37. 数字在排序数组中出现的次数
    [剑指offer] 36. 两个链表的第一个公共结点
    [剑指offer] 35. 数组中的逆序对
    vscode在win10 / linux下的.vscode文件夹的配置 (c++/c)
    [剑指offer] 34. 第一个只出现一次的字符
    [剑指offer] 33. 丑数
  • 原文地址:https://www.cnblogs.com/CodingXu-jie/p/14421392.html
Copyright © 2011-2022 走看看