《LeetCode之每日一题》:79.数组的度

Posted 是七喜呀!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《LeetCode之每日一题》:79.数组的度相关的知识,希望对你有一定的参考价值。

数组的度


题目链接: 数组的度

有关题目

给定一个非空且只包含非负数的整数数组 nums,
数组的度的定义是指数组里任一元素出现频数的最大值。

你的任务是在 nums 中找到与 nums 拥有相同大小的度的
最短连续子数组,返回其长度。

示例 1:

输入:[1, 2, 2, 3, 1]
输出:2
解释:
输入数组的度是2,因为元素12的出现频数最大,均为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
提示:

nums.length 在150,000 区间范围内。
nums[i] 是一个在 049,999 范围内的整数。

题解

方法一:哈希表

思路:
使用hash记录,num[i]出现的首末位置,根据最短长度的子数组,首位一定为nums[i],求出最短长度
class Solution {
public:
    int findShortestSubArray(vector<int>& nums) {
        int n = nums.size();
        unordered_map<int,vector<int>> mp;
        for(int i = 0; i < n; ++i){
            if (mp.count(nums[i])){
                mp[nums[i]][0]++;//频数加1
                mp[nums[i]][2] = i;//更新nums[i]最后出现的位置
            }
            else
                mp[nums[i]] = {1, i, i};//未出现nums[i]频数置为1,更新nums[i]第一次与最后一次出现的位置
        }
        int maxNum = 0, minLen = 0;//出现次数最多的数字频数为maxNum,对应的最短连续子数组的长度minLen
        for (auto& [_,vec] : mp){
            if (maxNum < vec[0]){
                maxNum = vec[0];
                minLen = vec[2] - vec[1] + 1;
            }
            //可能存在频数相同的数字,但存在不同的最小对应的子数组的长度
            else if (maxNum == vec[0]){
                if (minLen > vec[2] - vec[1] + 1)
                    minLen = vec[2] - vec[1] + 1;
            }
        }
        return minLen;
    }
};

在这里插入图片描述
法二:滑动窗口

//Java
class Solution {
    public int findShortestSubArray(int[] nums) {
        int n = nums.length;
        int[] freq = new int[50000];//记录频数,根据题意创建最大数组长度为50000
        int degree = 0;//记录数组的度
        for (int i = 0; i < n; ++i){
            degree = Math.max(degree,++freq[nums[i]]);
        }
        Arrays.fill(freq,0);//重置freq数组元素为零
        int left = 0, right = 0, minSpan = Integer.MAX_VALUE;//
        while(right < n){
            ++freq[nums[right]];//右窗口滑进一个数,其频数加1
            while(left <= right && degree == freq[nums[right]]){//满足数组的度
                minSpan = Math.min(right - left + 1, minSpan);
                freq[nums[left++]]--;//数组的度所满足的最小长度的子数组,首位元素比相同
                                     //即nums[left] == nums[right] 为真
            }
            right++;//扩大右窗口边界
        }
        return minSpan;
    }
}

时间复杂度:O(N)
空间复杂度:O(N)

以上是关于《LeetCode之每日一题》:79.数组的度的主要内容,如果未能解决你的问题,请参考以下文章

leetcode刷题 64.数组的度——Java版

《LeetCode之每日一题》:215.打乱数组

《LeetCode之每日一题》:49.连续数组

《LeetCode之每日一题》:60.搜索旋转排序数组

《LeetCode之每日一题》:272.最大子数组和

《LeetCode之每日一题》:17. 旋转数组