这是我参与「掘金日新计划 · 2 月更文挑战」的第 2 天,点击查看活动详情
问题描述
给定一个非空且只包含非负数的整数数组 nums,数组的 度 的定义是指数组里任一元素出现频数的最大值。
你的任务是在 nums 中找到与 nums 拥有相同大小的度的最短连续子数组,返回其长度。
示例 1:
输入: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 。
示例 2:
输入:nums = [1,2,2,3,1,4,2]
输出:6
解释:
数组的度是 3 ,因为元素 2 重复出现 3 次。
所以 [2,2,3,1,4,2] 是最短子数组,因此返回 6 。
提示:
- nums.length 在 1 到 50,000 范围内。
- nums[i] 是一个在 0 到 49,999 范围内的整数。
思路分析
首先我们先要理解一下题目意思,题目会给我们一个数组,我们需要在 nums 中找到与 nums 拥有相同大小的度的最短连续子数组,返回其长度。数组的 度 的定义是指数组里任一元素出现频数的最大值。如:数组[1,2,2,3,1,4,2]的度为 3,因为在数组中出现次数最多的元素时 2,其出现的次数为 3,所以该数组的度也为 3。我们可以通过以下步骤来解答这道题目:
- 1、统计数组中所有元素的频次及长度
我们可以通过哈希表将数组中所有元素出现的频次进行统计,并记录其中最大的频次值。我们可以记录每个元素第一次出现的位置及最后一次出现的位置,通过这两个位置下标我们就可以计算出子数组的长度。
const map = {};
let res = Infinity,
maxNums = 0;
for (let i = 0; i < nums.length; i++) {
if (!map[nums[i]]) {
map[nums[i]] = {
nums: 1,
left: i,
right: i,
};
} else {
map[nums[i]].nums++;
map[nums[i]].right = i;
}
maxNums = Math.max(maxNums, map[nums[i]].nums);
}
- 2、根据哈希表统计信息及最大频次,计算出拥有最大度的子数组的最短长度
for (let k in map) {
if (map[k].nums == maxNums) {
const { right, left } = map[k];
res = Math.min(res, right - left + 1);
}
}
完整 AC 代码如下:
AC 代码
/**
* @param {number[]} nums
* @return {number}
*/
var findShortestSubArray = function (nums) {
const map = {};
let res = Infinity,
maxNums = 0;
for (let i = 0; i < nums.length; i++) {
if (!map[nums[i]]) {
map[nums[i]] = {
nums: 1,
left: i,
right: i,
};
} else {
map[nums[i]].nums++;
map[nums[i]].right = i;
}
maxNums = Math.max(maxNums, map[nums[i]].nums);
}
for (let k in map) {
if (map[k].nums == maxNums) {
const { right, left } = map[k];
res = Math.min(res, right - left + 1);
}
}
return res;
};
说在后面
大家好,这里是葛藟,本人为算法业余爱好者,平时只是随着兴趣偶尔刷刷题,如果上面分享有错误的地方,欢迎指出,感激不尽。