1838.最高频元素的频数

思路:一开始我是使用暴力解法,先排序,一个一个元素遍历,从该元素最近的一个数(左边)往左求它们的差值和直到超出了目标值k,再存所包含的最大元素个数,然后就超出时间限制了:

class Solution {
public:
    int maxFrequency(vector<int>& nums, int k) {
        sort(nums.begin(),nums.end());
        int result(1);
        for(int i=1;i<nums.size();++i)
        {
            int j=i-1;
            int n=k;
            int mid(1);
            while(j>=0)
            {
                if(nums[i]-nums[j]<=n)
                {
                    ++mid;
                    n-=(nums[i]-nums[j]);
                    --j;
                }
                else break;
            }
            if(result<mid) result=mid;
        }
        return result;
    }
};

然后看了解题区的思路,利用滑动窗口,不断将窗口右边界右移,如果超出了k就向右移动左边界,如下

class Solution {
public:
    int maxFrequency(vector<int>& nums, int k) {
        sort(nums.begin(),nums.end());//要先排序
        int result(1);//记录结果
        int mid(1);//存放中途中出现的总个数
        long long t=k;//存放还能被允许的差值和
        for(int i=1,j=0;i<nums.size();)
        {
            //对于numsp[i]其实还未放入窗口中,即正在考虑如何放
            //所以目前的状况是,窗口内的所有数能够与nums[i-1]相等
            //因此要判断能不能都与nums[i]相等,就要判断达到nums[i]的差值和是否在t内
            //因为目前大家都等于了nums[i-1],所以还需要的差值和就为如下判断条件里的式子
            //这里可能会超出int的范围,所以要用long long类型
            if((long long)(nums[i]-nums[i-1])*(i-j)<=t)
            {
                //在能承受范围内,就要减去这部分代价,目前所有数就等于了nums[i]
                t-=(long long)(nums[i]-nums[i-1])*(i-j);
                //nums[i]加入了窗口
                ++mid;
                //判断下一个数
                ++i;
            }
            //如果超出了接受范围
            else
            {
                //这里的话目前窗口达到了一个上限,所以需要判断保留最大值
                if(mid>result) result=mid;
                //这里是把最左边界的元素去除,所以要加上差值
                t+=(nums[i-1]-nums[j]);
                //左边界右移
                ++j;
                //失去一个元素
                --mid;
            }
        }
        //返回最大
        return max(result,mid);
    }
};

你可能感兴趣的:(算法小练习,leetcode,c++,算法)