题目:
元素的 频数 是该元素在一个数组中出现的次数。
给你一个整数数组 nums 和一个整数 k 。在一步操作中,你可以选择 nums 的一个下标,并将该下标对应元素的值增加 1 。
执行最多 k 次操作后,返回数组中最高频元素的 最大可能频数 。
算法:
方法一:双指针
关键是双指针移动时,如何消耗和还原usedK。可能画图模拟一下这个过程比较容易找到思路
func maxFrequency(nums []int, k int) int {
sort.Ints(nums)
usedK := 0
ans := 0
for left, right := 0, 0; right < len(nums); right ++ {
if right > 0 {
usedK = usedK + (right - left) * (nums[right] - nums[right - 1])
}
for usedK > k {
usedK = usedK - (nums[right] - nums[left])
left ++
}
if right - left + 1 > ans {
ans = right - left + 1
}
}
return ans
}
方法二:前缀和
[1,2,5,6]变为[5,5,5,6]需要消耗多少个k呢?可以通过前缀和快速进行计算:num[2] * 3 - sum[2]。 通用公式为:消耗的k = 区间[left, right]所有数变成num[right]的数字之和 - 原有区间和 = num[right] * (right - left + 1) - (sum[right] - sum[left - 1])
func maxFrequency(nums []int, k int) int {
sort.Ints(nums)
sum := make([]int, len(nums) + 1)
for i := range nums {
sum[i + 1] = sum[i] + nums[i]
}
left, right := 0, len(nums)
for left < right {
mid := (left + right + 1) >> 1
if check(sum, nums, mid, k) {
left = mid
} else {
right = mid - 1
}
}
return left
}
func check(sum, nums []int, length , limit int) bool {
for left := 0; left + length - 1 < len(nums); left ++ {
right := left + length - 1
if nums[right] * length - (sum[right + 1] - sum[left]) <= limit {
return true
}
}
return false
}