LeetCode 每日一题「最高频元素的频数」

Posted 陈皮的JavaLib

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode 每日一题「最高频元素的频数」相关的知识,希望对你有一定的参考价值。

我是陈皮,一个在互联网 Coding 的 ITer,微信搜索「陈皮的JavaLib」第一时间阅读最新文章,回复【资料】,即可获得我精心整理的技术资料,电子书籍,一线大厂面试资料和优秀简历模板。

题目


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

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

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

示例1:

  • 输入: nums = [1,2,4], k = 5
  • 输出:3
  • 解释:对第一个元素执行 3 次递增操作,对第二个元素执 2 次递增操作,此时 nums = [4,4,4] 。4 是数组中最高频元素,频数是 3 。

示例2:

  • 输入:nums = [1,4,8,13], k = 5
  • 输出:2
  • 解释:存在多种最优解决方案:
    • 对第一个元素执行 3 次递增操作,此时 nums = [4,4,8,13] 。4 是数组中最高频元素,频数是 2 。
    • 对第二个元素执行 4 次递增操作,此时 nums = [1,8,8,13] 。8 是数组中最高频元素,频数是 2 。
    • 对第三个元素执行 5 次递增操作,此时 nums = [1,4,13,13] 。13 是数组中最高频元素,频数是 2 。

示例3:

  • 输入:nums = [3,9,6], k = 2
  • 输出:1

提示

  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= 105
  • 1 <= k <= 105

题目来源:LeetCode


分析


最简单的解法就是使用暴力法,先对原数组进行排序,然后对数组中的每一个元素,对它前面的元素往前遍历,在操作次数不超过 k 的情况下,频数加一,直到操作次数超过 k 则终止。时间复杂度为 O(n^2)。

package com.chenpi;

import java.util.Arrays;

/**
 * @Description
 * @Author 陈皮
 * @Date 2021/7/19
 * @Version 1.0
 */
public class MaxFrequency {

    public int maxFrequency(int[] nums, int k) {
        // 从小到大排序
        Arrays.sort(nums);
        // 记录滑动过程中的最大频数
        int max = 0;
        // 从左往后(小到大)遍历每一个元素nums[j],判断它是否那个最大频数的元素
        for (int j = 0; j < nums.length; j++) {
            int i = j;
            int tempK = k;
            while (i >= 0 && ((nums[j] - nums[i]) <= tempK)) {
                tempK -= nums[j] - nums[i];
                i--;
            }
            max = Math.max(max, j - i);
        }
        return max;
    }

    public static void main(String[] args) {
        MaxFrequency maxFrequency = new MaxFrequency();
        int[] nums = {1, 2, 4};
        System.out.println(maxFrequency.maxFrequency(nums, 5));
    }
}

不过上述解法在数组长度很大的时候,执行比较耗时。其实这道题考察的是滑动窗口解法,先将数组从小到大排序,然后遍历数组每一个元素,看它的左边窗口最大长度即这个元素的频数,然后求出这些频数的最大值即可。

package com.chenpi;

import java.util.Arrays;

/**
 * @Description
 * @Author 陈皮
 * @Date 2021/7/19
 * @Version 1.0
 */
public class MaxFrequency {

    public int maxFrequency(int[] nums, int k) {
        // 从小到大排序
        Arrays.sort(nums);
        // 记录滑动过程中的最大频数
        int max = 0;
        int tempSum = 0;
        // 从左往后(小到大)遍历每一个元素nums[j],判断它是否那个最大频数的元素
        for (int i = 0, j = 0; j < nums.length; j++) {
            // j-i是滑动窗口元素的个数(排除窗口内最后一个元素nums[j])
            // nums[j] * (j - i) - tempSum 窗口前面几个元素的差值
            // 如果差值超过k则代表不满足,左窗口需要往后滑动一位,并减去这个调出窗口的元素值
            while (nums[j] * (j - i) - tempSum > k) {
                tempSum -= nums[i++];
            }
            // 右窗口往后滑动一位,并且窗口总值加上当前元素
            tempSum += nums[j];
            // 之前窗口的最大频数和当前窗口频数哪个大
            max = Math.max(max, j - i + 1);
        }
        return max;
    }

    public static void main(String[] args) {
        MaxFrequency maxFrequency = new MaxFrequency();
        int[] nums = {1, 4, 8, 13};
        System.out.println(maxFrequency.maxFrequency(nums, 5));
    }

}

在这里插入图片描述


上一题与下一题


上一题LeetCode 每日一题「罗马数字转整数」

下一题:敬请期待

以上是关于LeetCode 每日一题「最高频元素的频数」的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode 每日一题「最高频元素的频数」

LeetCode 1838. 最高频元素的频数 /76. 最小覆盖子串/727. 最小窗口子序列(动规,难)

Leetcode——最高频元素的频数

LeetCode 1838 最高频元素的频数[滑动窗口] HERODING的LeetCode之路

leetcode每日一题前k个高频单词

《LeetCode之每日一题》:35. 前K个高频单词