枚举
解法:枚举
如果最后的众数是 $x$,那么答案就是 $c_x + \min(m, \sum\limits_{x - k \le i \le x + k, i \ne x} c_i)$,其中 $c_x$ 是 nums
里 $x$ 的数量,$m$ 是操作次数。
这个式子的值会随着 $x$ 的变化发生怎样的改变?$c_x$ 肯定在 $x$ 取到 nums
里有的数时才尽可能大,而 $\sum\limits_{x - k \le i \le x + k, i \ne x} c_i$ 的值和 $x$ 被几个数的“范围”覆盖到有关。一个数 $x$ 能覆盖的范围是 $[x - k, x + k]$,当 $x$ 增加到某个区间的左端点时,被覆盖到的数量会增加 $1$,之后在区间中间不发生变化。
所以我们只要考虑 $x$ 取 nums
中出现的数,以及它们 $-k$,共 $2n$ 种数。$\sum$ 的值可以用二分的方式快速计算。复杂度 $\mathcal{O}(n\log n)$。
参考代码(c++)
###cpp
class Solution {
public:
int maxFrequency(vector<int>& nums, int k, int numOperations) {
// 把所有要考虑的值放进 set 里
unordered_set<int> st;
// 统计 nums 里每种数出现了几次
unordered_map<int, int> mp;
for (int x : nums) {
st.insert(x); st.insert(x - k);
mp[x]++;
}
// 给 nums 排序,方便接下来二分计数。
sort(nums.begin(), nums.end());
int ans = 0;
for (int x : st) {
int tmp = 0;
// 二分计算 (x, x + k] 里有几个数
tmp += upper_bound(nums.begin(), nums.end(), x + k) - upper_bound(nums.begin(), nums.end(), x);
// 二分计算 [x - k, x) 里有几个数
tmp += lower_bound(nums.begin(), nums.end(), x) - lower_bound(nums.begin(), nums.end(), x - k);
tmp = min(tmp, numOperations);
ans = max(ans, mp[x] + tmp);
}
return ans;
}
};