题目地址:
给定一个长 n n n数组 a a a和一个非负整数 k k k,再给定给一个非负整数 o o o,要求必须做 o o o次操作,每次操作可以将未操作过的一个数加上 [ − k , k ] [-k,k] [−k,k]的一个整数。对于所有操作的方案,问最终得到的数组里频率最大的数的频率可能是多少。题目保证 a a a中的数都是正整数。
先做一下频率计数,然后暴力枚举要变成的数是几,如果要变成 x x x,那么能变成 x x x的数的范围必然是 [ x − k , x + k ] [x-k,x+k] [x−k,x+k],可以利用计数数组的前缀和数组来 O ( 1 ) O(1) O(1)求出。那么能变成 x x x的数的个数由两个因素决定,一个是 o o o的大小,另一个是 ∣ { y ∈ a : y ∈ [ x − k , x + k ] ∧ y ≠ x } ∣ |\{y\in a:y\in[x-k,x+k]\land y\ne x\}| ∣{y∈a:y∈[x−k,x+k]∧y=x}∣,这两个较小者再加上 ∣ { y ∈ a : y = x } ∣ |\{y\in a:y= x\}| ∣{y∈a:y=x}∣即为能变成 x x x的数的个数。暴力枚举所有的 x x x的可能性即可。代码如下:
class Solution {
public:
int maxFrequency(vector<int>& a, int d, int ops) {
int max_v = *max_element(a.begin(), a.end());
int cnt[max_v], s[max_v + 1];
memset(cnt, 0, sizeof cnt);
memset(s, 0, sizeof s);
for (int x : a) cnt[x - 1]++;
for (int i = 1; i <= max_v; i++) s[i] = s[i - 1] + cnt[i - 1];
int res = 1;
for (int i = 0; i < max_v; i++) {
int l = max(0, i - d), r = min(max_v - 1, i + d);
res = max(res, min(s[r + 1] - s[l] - cnt[i], ops) + cnt[i]);
}
return res;
}
};
时间复杂度 O ( max a + n ) O(\max a+n) O(maxa+n),空间 O ( max a ) O(\max a) O(maxa)。