LeetCode——1838. 最高频元素的频数

最高频元素的频数

  • 题目
  • 思路
  • 代码
  • 结果

题目

元素的 频数 是该元素在一个数组中出现的次数。

给你一个整数数组 nums 和一个整数 k 。在一步操作中,你可以选择 nums 的一个下标,并将该下标对应元素的值增加 1 。

执行最多 k 次操作后,返回数组中最高频元素的 最大可能频数 。

思路

自己是没有什么思路的,知道说应该要进行一个排序,但是不知道应该使用哪一种算法进行解决!

看了题解,总算有点点思路!
LeetCode——1838. 最高频元素的频数_第1张图片
操作数组后,一定是将所有数字变为其中的某一个数字。提示1解释得挺清楚的,因为结果只是求最高频元素的频数,这个时候,我们统一变成一个比最大那个数。在结果看来,我们只是影响了最高频元素的大小,并不影响最高频元素的频数

提示2,优先操作距离目标值最近的元素,因为我们对数组进行了一个排序,数组一定是从小到大进行排序的,比如右边的数是5,左边的是1,中间的是3,那肯定是操作3使得3变成5的步数比操作1变成5的步数要少!
LeetCode——1838. 最高频元素的频数_第2张图片
这里的推导要自己去推导一下,就是在原有的基础上,假设向右移动,那么就会增加总的步数,向左移动,会减少总的步数。【每次都是将某个数字左边的所有数字变为该数字】,这样子,每次拿当前频数与操作后结果的频数进行一个比较,最终可以获得将步数k利用到极致的情况下,所能够获得的最高频元素的频数!

代码

class Solution {
    public int maxFrequency(int[] nums, int k) {
        // 对数组进行一个升序排序
        Arrays.sort(nums);
        
        // 数组的长度
        int length = nums.length;

        // 需要操作的总步数,必须保证这个数小于等于k才符合条件
        long total = 0;
        // 左指针为0,右指针为1
        int l = 0;
        int ans = 1;
        for (int i= 1; i < length; ++i) 
        {
            total += (long) (nums[i] - nums[i-1]) * (i-l);
            // 当总步数大于k时,移动左指针缩小步数
            while (total > k) 
            {
                // 根据推算,不动右指针,右移左指针会减少这么多步数
                total-= nums[i]-nums[l];
                ++l;
            }
            ans = Math.max(ans,i-l + 1);
        }
        return ans;
    }
}

结果

LeetCode——1838. 最高频元素的频数_第3张图片
结果很强,从来对滑动窗口没什么概念,今天算是见识到了滑动窗口的好处。如果使用暴力,真的浪费了巨大的计算量!

你可能感兴趣的:(LeetCode)