持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第18天,点击查看活动详情
前言
做事要有度,今天来一道数组相关的题目,本来看简单题目以为很简单,但做着做着就有点懵逼了,废话不多说,直接上题目。
题目描述
给定一个非空且只包含非负数的整数数组 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 。
解题思路
这一题是虽然是简单难度的题目,但其中需要注意的点还是挺多的,而且我感觉题目有混淆视听的嫌疑,那就是题目中提到的连续子数组,我刚看到题目的时候想过把所有的子数组都列出来,但其实并不然,只要找到最长的满足条件的子数组就可以了。
- 首先要找出数组中出现频数最多的项,这里要特别注意,这个项可能不是一个(很重要)
- 用map来记录数组中各项出现的频数
- 利用for...of...找到map中最大的value,也就是度
- 接着再循环map,当map项的值等于度时就循环数组,如果当前项登录度对应的值时就存入数组;这里分两种情况,第一种情况是当结果数组,也就是resultArr为空并且还没遇到度对应的key时;一种是当resultArr已经有项并且遇到项不等于key时,这时也要push进resultArr
- 没当遇到项等于key时,除了要push进数组外,degree也要减减
- 这里用maxLength来记录最短连续子数组,因此要分两种情况,第一种是整个数组中出现频数最多的值是唯一的情况,那这时候maxLength = resultArr.length即可;另一种就是数组中频数最多的值不值一个,那就要取resultArr.length最短的那个了
代码如下:
/**
* @param {number[]} nums
* @return {number}
*/
var getMax = function (map) {
let max = 0
for (let [key, value] of map) {
if (value > max) {
max = value
}
}
return max
}
var findShortestSubArray = function (nums) {
var maxLength = 0
var map = new Map()
for (let i = 0; i < nums.length; i++) {
if (!map.get(nums[i])) {
map.set(nums[i], 1)
} else {
map.set(nums[i], map.get(nums[i]) + 1)
}
}
for (let [key, value] of map) {
let degree = getMax(map)
if (value === degree) {
let resultArr = []
for (let j = 0; j < nums.length && degree > 0; j++) {
if (resultArr.length === 0 && nums[j] === key) {
resultArr.push(nums[j])
degree--
} else if (resultArr.length > 0) {
resultArr.push(nums[j])
if (nums[j] === key) {
degree--
}
}
}
if (!maxLength) {
maxLength = resultArr.length
}
if (maxLength > resultArr.length) {
maxLength = resultArr.length
}
}
}
return maxLength
};
运行结果如下图: