2025-06-01:执行操作后元素的最高频率Ⅰ。用go语言,给定一个整数数组 nums 和两个整数 k 以及 numOperations。 你需要对数组 nums 进行恰好 numOperation

#『技术文档』写作方法征文挑战赛#

2025-06-01:执行操作后元素的最高频率Ⅰ。用go语言,给定一个整数数组 nums 和两个整数 k 以及 numOperations。

你需要对数组 nums 进行恰好 numOperations 次操作。每次操作的步骤如下:

  • 选择一个之前没有选择过的下标 i。

  • 将 nums[i] 增加一个在区间 [-k, k] 内的任意整数。

完成所有操作后,计算数组中出现次数最多的元素出现的频率,并返回这个最大频率。

1 <= nums.length <= 100000。

1 <= nums[i] <= 100000。

0 <= k <= 100000。

0 <= numOperations <= nums.length。

输入:nums = [5,11,20,20], k = 5, numOperations = 1。

输出:2。

解释:

通过以下操作得到最高频率 2 :

将 nums[1] 增加 0 。

题目来自力扣3346。

关键观察:

  1. 排序:首先将数组排序,这样我们可以更容易地计算某个区间内的元素是否可以通过操作调整到同一个值。
  2. 滑动窗口:使用滑动窗口的思想来找到最长的子数组,其中所有元素可以通过最多 numOperations 次操作调整到同一个值。
  3. 操作分配:对于窗口内的元素,我们需要计算将它们调整到某个目标值(通常是窗口的右端或左端)所需的总操作次数,并确保这个总操作次数不超过 numOperations 的限制。

具体步骤:

  1. 排序数组:将 nums 排序,以便后续的滑动窗口处理。
  2. 初始化指针和变量:使用 leftright 指针表示滑动窗口的左右边界,cnt 用于统计当前窗口内相同元素的连续出现次数。
  3. 滑动窗口扩展
    • 对于每个元素 nums[i],尝试扩展窗口的右边界 right,使得窗口内的所有元素可以通过最多 numOperations 次操作调整到 nums[i]
    • 计算将窗口内所有元素调整到 nums[i] 所需的总操作次数。这可以通过前缀和或累加的方式计算。
    • 如果总操作次数超过 numOperations,则移动左边界 left 以减少操作次数。
    • 更新最大频率 ans
  4. 处理连续相同元素:如果当前元素与下一个元素相同,直接跳过,因为它们已经可以贡献频率。
  5. 考虑操作限制:由于最多只能进行 numOperations 次操作,因此最大频率不能超过 numOperations + 1(即最多调整 numOperations 个元素到某个值,加上该值本身可能已经存在)。

时间复杂度和空间复杂度

  • 时间复杂度
    • 排序:O(n log n),其中 nnums 的长度。
    • 滑动窗口:每个元素最多被访问两次(leftright 指针各一次),因此是 O(n)
    • 总时间复杂度:O(n log n)(排序主导)。
  • 空间复杂度
    • 排序可能需要 O(log n) 的栈空间(取决于排序算法)。
    • 其他变量是常数空间。
    • 总空间复杂度:O(log n)

Go完整代码如下:

package main

import (
	"fmt"
	"slices"
)

func maxFrequency(nums []int, k, numOperations int) (ans int) {
	slices.Sort(nums)

	n := len(nums)
	var cnt, left, right, left2 int
	for i, x := range nums {
		for nums[left2] < x-k*2 {
			left2++
		}
		ans = max(ans, min(i-left2+1, numOperations))

		cnt++
		// 循环直到连续相同段的末尾,这样可以统计出 x 的出现次数
		if i < n-1 && x == nums[i+1] {
			continue
		}
		for nums[left] < x-k {
			left++
		}
		for right < n && nums[right] <= x+k {
			right++
		}
		ans = max(ans, min(right-left, cnt+numOperations))
		cnt = 0
	}

	return
}

func main() {
	nums := []int{5,11,20,20}
	k := 5
	numOperations := 1
	result := maxFrequency(nums,k,numOperations)
	fmt.Println(result)
}

在这里插入图片描述

Python完整代码如下:

.

# -*-coding:utf-8-*-

from bisect import bisect_left, bisect_right

def maxFrequency(nums, k, numOperations):
    nums.sort()
    n = len(nums)
    ans = 0
    cnt = 0
    left = 0
    right = 0
    left2 = 0
    
    for i, x in enumerate(nums):
        while left2 < n and nums[left2] < x - 2 * k:
            left2 += 1
        ans = max(ans, min(i - left2 + 1, numOperations))
        
        cnt += 1
        if i < n - 1 and x == nums[i + 1]:
            continue
        
        while left < n and nums[left] < x - k:
            left += 1
        while right < n and nums[right] <= x + k:
            right += 1
        
        ans = max(ans, min(right - left, cnt + numOperations))
        cnt = 0
        
    return ans

if __name__ == "__main__":
    nums = [5, 11, 20, 20]
    k = 5
    numOperations = 1
    result = maxFrequency(nums, k, numOperations)
    print(result)

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

福大大架构师每日一题

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值