comments | difficulty | edit_url | rating | source | tags | |||||
---|---|---|---|---|---|---|---|---|---|---|
true |
困难 |
2444 |
第 376 场周赛 Q4 |
|
给你一个下标从 0 开始的整数数组 nums
和一个整数 k
。
你可以对数组执行 至多 k
次操作:
- 从数组中选择一个下标
i
,将nums[i]
增加 或者 减少1
。
最终数组的频率分数定义为数组中众数的 频率 。
请你返回你可以得到的 最大 频率分数。
众数指的是数组中出现次数最多的数。一个元素的频率指的是数组中这个元素的出现次数。
示例 1:
输入:nums = [1,2,6,4], k = 3 输出:3 解释:我们可以对数组执行以下操作: - 选择 i = 0 ,将 nums[0] 增加 1 。得到数组 [2,2,6,4] 。 - 选择 i = 3 ,将 nums[3] 减少 1 ,得到数组 [2,2,6,3] 。 - 选择 i = 3 ,将 nums[3] 减少 1 ,得到数组 [2,2,6,2] 。 元素 2 是最终数组中的众数,出现了 3 次,所以频率分数为 3 。 3 是所有可行方案里的最大频率分数。
示例 2:
输入:nums = [1,4,4,2,4], k = 0 输出:3 解释:我们无法执行任何操作,所以得到的频率分数是原数组中众数的频率 3 。
提示:
1 <= nums.length <= 105
1 <= nums[i] <= 109
0 <= k <= 1014
题目求的是在最多进行
因此,我们不妨先对数组
接下来,我们再分析,如果一个频率
我们二分枚举频率,定义二分查找的左边界
为了判断是否存在这样的子数组,我们可以使用前缀和。我们首先定义两个指针
我们可以通过前缀和数组
时间复杂度
class Solution:
def maxFrequencyScore(self, nums: List[int], k: int) -> int:
nums.sort()
s = list(accumulate(nums, initial=0))
n = len(nums)
l, r = 0, n
while l < r:
mid = (l + r + 1) >> 1
ok = False
for i in range(n - mid + 1):
j = i + mid
x = nums[(i + j) // 2]
left = ((i + j) // 2 - i) * x - (s[(i + j) // 2] - s[i])
right = (s[j] - s[(i + j) // 2]) - ((j - (i + j) // 2) * x)
if left + right <= k:
ok = True
break
if ok:
l = mid
else:
r = mid - 1
return l
class Solution {
public int maxFrequencyScore(int[] nums, long k) {
Arrays.sort(nums);
int n = nums.length;
long[] s = new long[n + 1];
for (int i = 1; i <= n; i++) {
s[i] = s[i - 1] + nums[i - 1];
}
int l = 0, r = n;
while (l < r) {
int mid = (l + r + 1) >> 1;
boolean ok = false;
for (int i = 0; i <= n - mid; i++) {
int j = i + mid;
int x = nums[(i + j) / 2];
long left = ((i + j) / 2 - i) * (long) x - (s[(i + j) / 2] - s[i]);
long right = (s[j] - s[(i + j) / 2]) - ((j - (i + j) / 2) * (long) x);
if (left + right <= k) {
ok = true;
break;
}
}
if (ok) {
l = mid;
} else {
r = mid - 1;
}
}
return l;
}
}
class Solution {
public:
int maxFrequencyScore(vector<int>& nums, long long k) {
sort(nums.begin(), nums.end());
int n = nums.size();
vector<long long> s(n + 1, 0);
for (int i = 1; i <= n; i++) {
s[i] = s[i - 1] + nums[i - 1];
}
int l = 0, r = n;
while (l < r) {
int mid = (l + r + 1) >> 1;
bool ok = false;
for (int i = 0; i <= n - mid; i++) {
int j = i + mid;
int x = nums[(i + j) / 2];
long long left = ((i + j) / 2 - i) * (long long) x - (s[(i + j) / 2] - s[i]);
long long right = (s[j] - s[(i + j) / 2]) - ((j - (i + j) / 2) * (long long) x);
if (left + right <= k) {
ok = true;
break;
}
}
if (ok) {
l = mid;
} else {
r = mid - 1;
}
}
return l;
}
};
func maxFrequencyScore(nums []int, k int64) int {
sort.Ints(nums)
n := len(nums)
s := make([]int64, n+1)
for i := 1; i <= n; i++ {
s[i] = s[i-1] + int64(nums[i-1])
}
l, r := 0, n
for l < r {
mid := (l + r + 1) >> 1
ok := false
for i := 0; i <= n-mid; i++ {
j := i + mid
x := int64(nums[(i+j)/2])
left := (int64((i+j)/2-i) * x) - (s[(i+j)/2] - s[i])
right := (s[j] - s[(i+j)/2]) - (int64(j-(i+j)/2) * x)
if left+right <= k {
ok = true
break
}
}
if ok {
l = mid
} else {
r = mid - 1
}
}
return l
}
function maxFrequencyScore(nums: number[], k: number): number {
nums.sort((a, b) => a - b);
const n = nums.length;
const s: number[] = Array(n + 1).fill(0);
for (let i = 1; i <= n; i++) {
s[i] = s[i - 1] + nums[i - 1];
}
let l: number = 0;
let r: number = n;
while (l < r) {
const mid: number = (l + r + 1) >> 1;
let ok: boolean = false;
for (let i = 0; i <= n - mid; i++) {
const j = i + mid;
const x = nums[Math.floor((i + j) / 2)];
const left = (Math.floor((i + j) / 2) - i) * x - (s[Math.floor((i + j) / 2)] - s[i]);
const right = s[j] - s[Math.floor((i + j) / 2)] - (j - Math.floor((i + j) / 2)) * x;
if (left + right <= k) {
ok = true;
break;
}
}
if (ok) {
l = mid;
} else {
r = mid - 1;
}
}
return l;
}