🏒

697. 数组的度

💚
难度: 简单

题目

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
提示:
  • nums.length 在1到 50,000 区间范围内。
  • nums[i] 是一个在 0 到 49,999 范围内的整数。

思路

  1. 先找到数组的度
  1. 再找到决定数组度的字符
  1. 计算出决定数组度字符的首尾长度

题解

// 697. 数组的度

/**
 * @param {number[]} nums
 * @return {number}
 */
var findShortestSubArray = function(nums) {
    // key: 数组字符, value: 出现次数
    let map = new Map()
    nums.forEach(n => {
        map.has(n) ? map.set(n, map.get(n) + 1) : map.set(n, 1)
    })
    // 找到数组的度, 可能有多个匹配项
    // [{ 数组字符, 出现次数 }]
    let maxArr = []
    map.forEach(((value, key) => {
        if (maxArr.length === 0) {
            maxArr.push({ key, value })
        } else {
            // 如果当前出现次数大于 maxArr 中出现次数, 则更新 maxArr
            if (value > maxArr[0].value) {
                // 清空数组
                maxArr.length = 0
                maxArr.push({ key, value })
            }
            // 相等就是相同度, 则 push
            if (value === maxArr[0].value) {
                maxArr.push({ key, value })
            }
        }
    }))
    // 找到数组度的元素的长度
    let minLength = []
    maxArr.forEach(m => {
        // 首次出现 index
        let firstIndex = nums.findIndex(n => n === m.key)
        // 最后一次出现 index
        let lastIndex
        for (let i = firstIndex; i < nums.length; i++) {
            if (nums[i] === m.key) {
                lastIndex = i
            }
        }
        // 做差, 获取与原数组度相等的最小长度数组
        minLength.push(lastIndex - firstIndex + 1)
    })
    // 多个度中的最小值
    return Math.min(...minLength)
};

// test
let arr = [1, 2, 2, 3, 1]
console.log(findShortestSubArray(arr))
结果
执行用时:104 ms, 在所有 JavaScript 提交中击败了60.37%的用户
内存消耗:41.6 MB, 在所有 JavaScript 提交中击败了92.63%的用户
通过测试用例:89 / 89
 

优化点