【LeetCode-697】数组的度

问题

给定一个非空且只包含非负数的整数数组 nums,数组的度的定义是指数组里任一元素出现频数的最大值。

你的任务是在 nums 中找到与 nums 拥有相同大小的度的最短连续子数组,返回其长度。

提示:

  • nums.length 在1到 50,000 区间范围内;
  • nums[i] 是一个在 0 到 49,999 范围内的整数。

示例

输入: [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.

输入:[1,2,2,3,1,4,2]
输出:6

解答1:哈希表

class Solution {
public:
    int findShortestSubArray(vector<int>& nums) {
        int minLen = INT_MAX, degree = 0;
        unordered_map<int, vector<int>> ump; // {最左坐标, 最右坐标, 出现次数}
        for (int i = 0; i < nums.size(); i++) {
            if (!ump.count(nums[i])) ump[nums[i]] = {i, i, 0};
            else ump[nums[i]][1] = i;
            ump[nums[i]][2]++;
        }
        for (auto& [_, v] : ump) {
            if (degree == v[2]) minLen = min(minLen, v[1] - v[0] + 1);
            else if (degree < v[2]) {
                degree = v[2];
                minLen = v[1] - v[0] + 1;
            }
        }
        return minLen;
    }
};

重点思路

使用一张哈希表存储数组中每个数的{最左坐标, 最右坐标, 出现次数}。本题的三个需要注意的点:1.当哈希表的值为vector之类的结构时,判断其中是否存在数据只能使用ump.count(xxx)这样的写法;2.对vector进行赋值之前,不要忘了初始化;3.遍历哈希表时,使用for (auto& [k, v] : ump)这样的形式,或者for(auto& kv : ump)然后使用kv.firstkv.second分别调用键与值。

本题首先遍历一遍数组,构建上述哈希表。再遍历一遍哈希表,确定频数最高数字的最小长度。

解答2:滑动窗口

class Solution {
public:
    int findShortestSubArray(vector<int>& nums) {
        int degree = 0, left = 0, right = 0, res = INT_MAX;
        int memo[50000]{};
        for (int i : nums) 
            degree = max(degree, ++memo[i]);
        memset(memo, 0, sizeof memo);
        while (right < nums.size()) {
            memo[nums[right]]++;
            while (memo[nums[right]] == degree) {
                res = min(res, right - left + 1);
                memo[nums[left++]]--;
            }
            right++;
        }
        return res;
    }
};

重点思路

先求出degree,然后使用滑动窗口。具体做法为,当滑动窗口内存在长度为度的数时,开始收缩窗口,直到不满足为止。这个过程不会漏算长度更小的数,但是可能会漏算长度更大的数,例如[2, 1, 1, 2],滑动窗口根本不会统计2, 1, 1, 2这一子数组,所以本题中滑动窗口法只能解决最短长度子数组的问题,如果要求刚好满足度的最长长度子数组,那么只能用解法1的哈希表算法。

posted @ 2021-02-20 20:25  tmpUser  阅读(38)  评论(0编辑  收藏  举报