在问 · 算法题解

697. 数组的度

题目描述

输入一个非空的非负整数数组 nums。数组的度定义为其中出现次数最多的元素的出现次数。

在 nums 的所有连续子数组中,找出度与整个数组的度相等的那些,返回其中最短的长度。

示例 1
输入:nums = [1,2,2,3,1]
输出:2

解释:整个数组的度为 2(1 和 2 各出现两次),最短的是 [2,2]。

示例 2
输入:nums = [1,2,2,3,1,4,2]
输出:6

解释:2 出现 3 次,覆盖所有 2 的最短片段是 [2,2,3,1,4,2]。

数据范围

  • nums.length 在 1 到 50000 之间。
  • nums[i] 是 0 到 49999 之间的整数。

解题思路

子数组要保持同样的度,就必须包含某个出现次数最多的元素的全部出现位置,最短就是从它第一次出现到最后一次出现的区间。所以用哈希表为每个值记录 [次数, 首次下标, 末次下标],再在次数等于度的值里取区间长度 r-l+1 最小的。

为什么正确

info[x] = [x 的出现次数, 首次下标, 末次下标];第二遍中 deg 是已看过的值的最大次数,best 是这些值中次数等于 deg 的最短区间长。

复杂度分析

时间 O(n),空间 O(n)。

易错点

度相同的元素可能有多个,要在它们之中取最短区间;只记第一个达到最大次数的元素会出错。区间长度是 r - l + 1,不要漏掉 +1。

参考代码

Python、Java、C++、Go、JavaScript、TypeScript 六种语言,逻辑一致。

class Solution:
    def findShortestSubArray(self, nums: List[int]) -> int:
        info = {}
        for i, x in enumerate(nums):
            if x in info:
                info[x][0] += 1
                info[x][2] = i
            else:
                info[x] = [1, i, i]
        deg = best = 0
        for cnt, l, r in info.values():
            if cnt > deg:
                deg, best = cnt, r - l + 1
            elif cnt == deg:
                best = min(best, r - l + 1)
        return best

载入编辑器,自己跑一遍 →

哈希表 专题的其他题目

查看 哈希表 全部题目 →