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

举报
福大大架构师每日一题 发表于 2025/06/01 06:49:22 2025/06/01
【摘要】 2025-06-01:执行操作后元素的最高频率Ⅰ。用go语言,给定一个整数数组 nums 和两个整数 k 以及 numOperations。你需要对数组 nums 进行恰好 numOperations 次操作。每次操作的步骤如下:选择一个之前没有选择过的下标 i。将 nums[i] 增加一个在区间 [-k, k] 内的任意整数。完成所有操作后,计算数组中出现次数最多的元素出现的频率,并返回这...

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)

在这里插入图片描述

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。