《LeetCode之每日一题》:79.数组的度
Posted 是七喜呀!
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《LeetCode之每日一题》:79.数组的度相关的知识,希望对你有一定的参考价值。
题目链接: 数组的度
有关题目
给定一个非空且只包含非负数的整数数组 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
提示:
nums.length 在1到 50,000 区间范围内。
nums[i] 是一个在 0 到 49,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.数组的度的主要内容,如果未能解决你的问题,请参考以下文章