数组的度

83 阅读3分钟

这是我参与「掘金日新计划 · 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;
};

说在后面

大家好,这里是葛藟,本人为算法业余爱好者,平时只是随着兴趣偶尔刷刷题,如果上面分享有错误的地方,欢迎指出,感激不尽。