【数组】力扣697:数组的度
给定一个非空且只包含非负数的整数数组 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。
解题思路@负雪明烛
- 先求原数组的度
求数组的度,本质还是求各个元素的出现次数,我们可以用 字典(哈希表)计数,字典的 key 是元素,value 是该元素出现的次数。因此,字典中所有 value 的最大值就是数组的度 degree。 - 再求与原数组相同度的最短子数组
- 要求的子数组的度与原数组相同度的相同,那么该子数组中也得有 degree 个重复的元素。比如对于示例二[1,2,2,3,1,4,2],出现次数最多的元素是 2,它的出现次数为 3, 所以数组的度为 3;我们要求的子数组得有 3 个 2 ,所以最短的子数组是 [2,2,3,1,4,2]。注意到了吗?我们要求的最短子数组的起始和终止位置,由出现次数最多的元素 第一次和最后一次出现的位置 确定。
- 另外,需要注意的是出现次数最多的元素可能不止一个,比如示例一[1, 2, 2, 3, 1],数字 1 和数字 2 都出现了 2 次。此时,我们必须分别对每个出现次数为 2 的元素(即数字 1 和数字 2 )都求一次包含2个它的最短子数组的长度(分别为5和2),最终对所有最短子数组长度取 min,得到结果为 2。
使用
left
和right
分别保存每个元素在数组中第一次出现的位置和最后一次出现的位置;使用counter
保存每个元素出现的次数。
数组的度 degree 等于counter.values()
的最大值;
对counter
再次遍历:如果元素 k 出现的次数等于 degree,则找出元素 k 最后一次出现的位置 和 第一次出现的位置,计算两者之差+1,即为子数组长度。
对所有出现次数等于 degree 的子数组的最短长度,取 min。
class Solution:
def findShortestSubArray(self, nums: List[int]) -> int:
left, right = dict(), dict()
counter = collections.Counter()
for i, num in enumerate(nums):
if num not in left:
left[num] = i
right[num] = i
counter[num] += 1
degree = max(counter.values())
res = len(nums)
for k, v in counter.items():
if v == degree:
res = min(res, right[k] - left[k] + 1)
return res
时间复杂度:O(N),因为对数组遍历了一遍,对counter 遍历了两遍。
空间复杂度:O(N),因为 counter 在最坏情况下会跟 nums 的元素个数相等。
作者:fuxuemingzhu
链接:https://leetcode-cn.com/problems/degree-of-an-array/solution/xiang-xi-fen-xi-ti-yi-yu-si-lu-jian-ji-d-nvdy/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix