1838. 最高频元素的频数

54 阅读1分钟

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

给你一个整数数组 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
}