697. 数组的度

toc

题目描述

给定一个非空且只包含非负数的整数数组 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 范围内的整数。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/degree-of-an-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

题目稍微有点绕,多读几遍还是可以理解的
根据题意,度即是元素出现的次数,求的度最大的数,从首次出现到最后一次出现的跨度,直接上代码吧

class Solution {
public:
    int findShortestSubArray(vector<int>& nums) {
        int iMaxDegree = 1;
        int iNumsSize = static_cast<int>(nums.size());
        std::unordered_map<int, int> unorderMapValueDegree;
        std::unordered_map<int, int> unorderMapValueLeft;
        std::unordered_map<int, int> unorderMapValueRight;
        std::unordered_map<int, int>::iterator itFind;
        for(int i = 0; i < iNumsSize; i++){
            int elem = nums[i];
            itFind = unorderMapValueDegree.find(elem);
            if(unorderMapValueDegree.end() == itFind){  //首次遇到,记录度与、元素最开始出现位置
                unorderMapValueDegree.insert(std::make_pair(elem, 1));
                unorderMapValueLeft.insert(std::make_pair(elem, i));
                unorderMapValueRight.insert(std::make_pair(elem, i));
            }else{  //已经出现过的元素,记录出现的位置,循环结束后,只记录了最后出现的位置
                itFind->second++;
                unorderMapValueRight[elem] = i;   
                iMaxDegree = max(iMaxDegree, itFind->second);     //记录下最大的度
            }
        }

        int iMinLen = iNumsSize;
        for(const auto& elem : unorderMapValueDegree){
            if(elem.second != iMaxDegree){
                continue;
            }
            iMinLen = min(unorderMapValueRight[elem.first] - unorderMapValueLeft[elem.first] + 1, iMinLen);
        }    
        return iMinLen;
    }
};

优化

上面的代码是利用map本身的key-value间的映射,将map换为数组,利用数组下标与值的对应关系,以空间换取时间的方式来提高性能

const int VALUECOUNT = 50000;
class Solution {
public:
    int findShortestSubArray(vector<int>& nums) {
        int iMaxDegree = 1, iValue = 0;
        int iNumsSize = static_cast<int>(nums.size());
        //nums元素做下标,数组元素存储元素对应度、首次出现位置、最后一次出现位置
        int iArrayDegree[VALUECOUNT] = {0}, iArrayLeftIndex[VALUECOUNT], iArrayRightIndex[VALUECOUNT];
        for(auto& elem : iArrayLeftIndex){
            elem = -1;
        }
        for(int i = 0; i < iNumsSize; i++){
            iValue = nums[i];
            iArrayDegree[iValue]++;
            if(-1 == iArrayLeftIndex[iValue]){
                iArrayLeftIndex[iValue] = i;
            }
            iArrayRightIndex[iValue] = i;   
            iMaxDegree = max(iMaxDegree, iArrayDegree[iValue]);
        }

        int iMinLen = iNumsSize;
        for(int i = 0; i < iNumsSize; i++){
            iValue = nums[i];
            if(iMaxDegree != iArrayDegree[iValue]){
                continue;
            }
            iMinLen = min(iMinLen, iArrayRightIndex[iValue] - iArrayLeftIndex[iValue] + 1);
        }
        return iMinLen;
    }
};


vector相比数组更安全、更灵活,我首次优化的时候选了vector,结果搞了个负优化。于是换成数组,并且在栈上创建,换完之后过然速度飞升。





原创不易,转载请注明出处,谢谢
原文地址:https://www.cnblogs.com/Keeping-Fit/p/14762914.html