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 1838. 最高频元素的频数 /76. 最小覆盖子串/727. 最小窗口子序列(动规,难)