力扣 1838. 最高频元素的频数

题目说明

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

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

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

  • 提示:

    • 1 <= nums.length <= 10^5
    • 1 <= nums[i] <= 10^5
    • 1 <= k <= 10^5

示例

示例 1:

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

示例 2:

1
2
3
4
5
6
输入: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:

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

笔者理解

此题是一道数组算法问题,在力扣题库中被定义为中等题。

解法

当笔者阅读完此题后,决定采用滑动窗口来求解,但时间空间效率欠优,让我们来看看具体如何实现的吧。

实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class Solution {
/*
* 滑动窗口
* 数组
*/
public int maxFrequency(int[] nums, int k) {
int n = nums.length;
// 至少有一个数
int result = 1;

// LinkedList实现双向队列,模拟滑动窗口
Deque<Integer> stack = new LinkedList<>();

// 将数组排序,保证在队列中的有序排列
Arrays.sort(nums);

stack.addLast(nums[0]);
// 记录元素和,用long是为了防止溢出
long sum = nums[0];

for (int i = 1 ; i < n; i++) {
stack.addLast(nums[i]);
sum += nums[i];
// 如果当前队列内的元素不符合要求,就移除队首元素,直到满足为止
while (sum + k < nums[i] * stack.size()) {
sum -= stack.removeFirst();
}
// 记录符合题意的最大可能频数
result = Math.max(result, stack.size());
}

return result;
}
}

时间空间效率都一般,可见此解法勉强还比较适合此题;

image.png

总结

本题是今天的每日一题,难度是为中等,感兴趣的朋友都可以去尝试一下,此题还有其他更多的解法,朋友们可以自己逐一尝试。