网易首页 > 网易号 > 正文 申请入驻

2026-07-23:产生至少 K 个峰值的最少操作次数。用go语言,给定一个长度为 n 的整数数组,该数组在逻辑上是首尾相连的(即下标 0 的前一

0
分享至

2026-07-23:产生至少 K 个峰值的最少操作次数。用go语言,给定一个长度为 n 的整数数组,该数组在逻辑上是首尾相连的(即下标 0 的前一个是 n-1,下标 n-1 的后一个是 0)。

如果一个下标上的元素值比它相邻的两个元素值都大,则称该下标为一个“峰值”。这里的相邻关系要考虑循环连接。

你可以不断执行以下操作:任选一个下标,将其对应的值加 1。操作次数没有限制。

目标是让数组中峰值的个数至少达到 k。请计算达成该目标所需的最少操作次数。如果无论如何操作都无法得到至少 k 个峰值,则返回 -1。

2 <= n == nums.length <= 5000。

-100000 <= nums[i] <= 100000。

0 <= k <= n。

输入: nums = [2,1,2], k = 1。

输出: 1。

解释:

为了实现至少 k = 1 个峰值,我们可以将 nums[2] = 2 增加到 3。

执行此操作后,nums[2] = 3 严格大于其相邻元素 nums[0] = 2 和 nums[1] = 1。

因此,所需的最小操作数是 1。

题目来自力扣3892。

1. 可行性预判与快速返回

  • • 在一个长度为n的环形数组中,两个相邻元素不可能同时为峰值,因此峰值数量的理论上限为⌊n/2⌋。若给定的k > n/2,直接返回-1

  • • 遍历整个环形数组,统计已经满足“严格大于左右相邻元素”的峰值个数cnt。若cnt ≥ k,说明无需任何操作,返回0

2. 环形数组的破环处理

为了在线性数组上运行动态规划,需要把环形相邻关系正确映射到线性结构上。核心思想是:分别禁止原数组的第一个元素或最后一个元素成为峰值,从而覆盖所有环形下的合法情况(首尾不能同时为峰值,或其中之一不是峰值)。

  • 情况 A(假定最后一个元素nums[n-1]不是峰值):构建新数组arr1 = [nums[n-1], nums[0], nums[1], …, nums[n-1]]。这里nums[n-1]被放在最前面,为原本缺少左邻居的nums[0]提供正确的环形左邻居,而末尾多出的nums[n-1]仅作邻居参考,不会被选为峰值。

  • 情况 B(假定第一个元素nums[0]不是峰值):构建新数组arr2 = [nums[0], nums[1], …, nums[n-1], nums[0]]。这里nums[0]被放在最后面,为原本缺少右邻居的nums[n-1]提供正确的环形右邻居,而开头的nums[0]仅作邻居参考,不会被选为峰值。

  • • 对arr1arr2分别调用线性版本的solve函数,取两次结果的最小值作为最终答案。

3. 线性版本的动态规划(solve 函数)

线性数组a(长度为m = n+1)上的 DP,目标是选出恰好 k 个不相邻的位置作为峰值,并使总操作代价最小。

  • 状态定义f[i]表示在子数组a[0…i]中选出当前阶段所需数量的不相邻峰值的最小操作代价。数组f长度为m,初始全0(代表选 0 个峰值的代价为 0)。

  • 逐层递推:外层循环left1k,每次计算在数组中选出left个峰值的最小代价。

    • • 进入第left层时,f中存放的是已选出left-1个峰值的状态。用两个变量f0f1临时保存前两个位置的旧状态,用于滚动更新。

    • • 将f[left*2-1]设为一个极大值(表示在长度不足的区间内无法选出left个不相邻峰值)。

    • • 内层循环ileft*2-1遍历到m-2-(k-left)*2(这个上界预留了后续还能选出剩余峰值的空间):

      • notChoose = f[i]:不选择位置i作为新峰值,代价沿用已考虑到i的状态。

      • choose = f0 + max( max(a[i-1], a[i+1]) - a[i] + 1, 0 ):选择位置i作为峰值,需将a[i]提升至严格大于两邻居的最大值,这个操作代价加上前一阶段(left-1个峰值,且最后选的位置在i-2或以前)的代价。

      • • 取min(notChoose, choose)更新到f[i+1],同时滚动f0f1以备下一轮使用。

  • • 完成k层循环后,f[m-1]即为在该线性数组上选出k个峰值的最小操作次数。

4. 峰值成本的局部计算

在上述 DP 的choose中,将位置i变为峰值所需的操作次数为max( max(a[i-1], a[i+1]) - a[i] + 1, 0 )。因为只能增加数值,所以必须把a[i]提升到至少max(左邻居, 右邻居) + 1,操作次数即为该值与当前值的差值(若非正则无需操作)。

复杂度分析

  • 时间复杂度solve函数的外层循环执行k次,内层循环长度约为m - 2k量级(m = n+1)。总 DP 转移次数为O(k·(n - k))。最坏情况k ≈ n/2,复杂度达到O(n²)。对于n ≤ 5000,该复杂度在可接受范围内。minOperations调用两次solve,总时间复杂度仍为O(n²)

  • 额外空间复杂度solve中维护了一维 DP 数组f,长度n+1;每次调用时需要构造临时数组arr1arr2,大小也为n+1。因此总额外空间复杂度为O(n)

Go完整代码如下:

package main

import (
"fmt"
"math"
)

// 非环形版本
func solve(a []int, k int) int {
n := len(a)
f := make([]int, n)
for left := 1; left <= k; left++ {
f0, f1 := f[left*2-2], f[left*2-1]
f[left*2-1] = math.MaxInt / 2
for i := left*2 - 1; i < n-1-(k-left)*2; i++ {
// 选或不选
notChoose := f[i]
choose := f0 + max(max(a[i-1], a[i+1])-a[i]+1, 0)
f0 = f1
f1 = f[i+1] // 保存旧数据
f[i+1] = min(notChoose, choose)
}
}
return f[n-1]
}

func minOperations(nums []int, k int) int {
n := len(nums)
if k > n/2 {
return -1
}

cnt := 0
for i, x := range nums {
if nums[(i-1+n)%n] < x && x > nums[(i+1)%n] {
cnt++
}
}
if cnt >= k { // 优化:已经有至少 k 个峰值了,无需操作
return 0
}

// 如果 nums[0] 是峰值,那么 nums[n-1] 不是峰值
ans1 := solve(append([]int{nums[n-1]}, nums...), k)
// 如果 nums[0] 不是峰值
ans2 := solve(append(nums, nums[0]), k)
return min(ans1, ans2)
}

func main() {
nums := []int{2, 1, 2}
k := 1
result := minOperations(nums, k)
fmt.Println(result)
}

Python完整代码如下:

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

import math
from typing import List

def solve(a: List[int], k: int) -> int:
"""非环形版本:在数组 a 中选出 k 个不相邻的峰值所需的最小操作数"""
n = len(a)
f = [0] * n
for left in range(1, k + 1):
f0, f1 = f[left * 2 - 2], f[left * 2 - 1]
f[left * 2 - 1] = math.inf
end = n - 1 - (k - left) * 2
for i in range(left * 2 - 1, end):
not_choose = f[i]
choose = f0 + max(max(a[i - 1], a[i + 1]) - a[i] + 1, 0)
f0, f1 = f1, f[i + 1] # 保存旧值并滑动
f[i + 1] = min(not_choose, choose)
return f[n - 1]

def minOperations(nums: List[int], k: int) -> int:
n = len(nums)
if k > n // 2:
return -1

# 已有峰值计数
cnt = 0
for i in range(n):
if nums[(i - 1) % n] < nums[i] > nums[(i + 1) % n]:
cnt += 1
if cnt >= k:
return 0

# 情况1:假设原数组的首元素是峰值 -> 尾元素不能是峰值
arr1 = [nums[-1]] + nums
ans1 = solve(arr1, k)

# 情况2:原数组的首元素不是峰值
arr2 = nums + [nums[0]]
ans2 = solve(arr2, k)

return min(ans1, ans2)

if __name__ == "__main__":
nums = [2, 1, 2]
k = 1
print(minOperations(nums, k))

C++完整代码如下:

#include  

#include
#include
#include

using namespace std;

/**
* 非环形版本:在数组 a 中选出 k 个不相邻的峰值所需的最小操作数
* @param a 整数数组
* @param k 需要的峰值个数
* @return 最小操作数
*/
int solve(const vector& a, int k) {
int n = a.size();
vector f(n, 0);
for (int left = 1; left <= k; ++left) {
int f0 = f[left * 2 - 2];
int f1 = f[left * 2 - 1];
f[left * 2 - 1] = INT_MAX / 2; // 相当于正无穷
int end = n - 1 - (k - left) * 2;
for (int i = left * 2 - 1; i < end; ++i) {
int notChoose = f[i];
int choose = f0 + max(max(a[i - 1], a[i + 1]) - a[i] + 1, 0);
f0 = f1;
f1 = f[i + 1]; // 保存旧数据
f[i + 1] = min(notChoose, choose);
}
}
return f[n - 1];
}

/**
* 计算使循环数组包含至少 k 个峰值的最小操作数
* @param nums 循环整数数组
* @param k 目标峰值个数
* @return 最小操作数,不可能则返回 -1
*/
int minOperations(const vector& nums, int k) {
int n = nums.size();
// 峰值必须不相邻,因此最多 n/2 个
if (k > n / 2) return -1;

// 统计已有的峰值个数
int cnt = 0;
for (int i = 0; i < n; ++i) {
if (nums[(i - 1 + n) % n] < nums[i] && nums[i] > nums[(i + 1) % n]) {
++cnt;
}
}
if (cnt >= k) return 0; // 已经满足要求

// 情况1:假设原数组的首元素是峰值,则尾元素不能是峰值
vector a1;
a1.push_back(nums[n - 1]);
a1.insert(a1.end(), nums.begin(), nums.end());
int ans1 = solve(a1, k);

// 情况2:原数组的首元素不是峰值
vector a2 = nums;
a2.push_back(nums[0]);
int ans2 = solve(a2, k);

return min(ans1, ans2);
}

int main() {
vector nums = {2, 1, 2};
int k = 1;
cout << minOperations(nums, k) << endl;
return 0;
}

我们相信人工智能为普通人提供了一种“增强工具”,并致力于分享全方位的AI知识。在这里,您可以找到最新的AI科普文章、工具评测、提升效率的秘籍以及行业洞察。 欢迎关注“福大大架构师每日一题”,发消息可获得面试资料,让AI助力您的未来发展。

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
闲鱼能买到的东西有多离谱?

闲鱼能买到的东西有多离谱?

康富贵碎碎念
2026-08-05 12:12:01
一个团被敌三个师包围,失联七天竟零伤亡突围,彭德怀:提拔!

一个团被敌三个师包围,失联七天竟零伤亡突围,彭德怀:提拔!

芊芊子吟
2026-08-07 09:30:20
我出差刚回来,发现小姑子把我100多平的婴儿房改成麻将房,我没吭声,第二天就把房子挂出去卖了,婆家傻眼了

我出差刚回来,发现小姑子把我100多平的婴儿房改成麻将房,我没吭声,第二天就把房子挂出去卖了,婆家傻眼了

墨染尘香
2026-08-06 17:19:33
判罚引全网热议!日本3战全胜拿八强三席,国乒仅剩陈幸同一人

判罚引全网热议!日本3战全胜拿八强三席,国乒仅剩陈幸同一人

华轩体育
2026-08-07 09:18:30
WTT快报:直播间里的那声叹息,道尽了国乒小将的无奈

WTT快报:直播间里的那声叹息,道尽了国乒小将的无奈

眼界纵横
2026-08-07 19:25:52
Shams:雄鹿、骑士与快船积极接触掘金,商讨沃特森先签后换

Shams:雄鹿、骑士与快船积极接触掘金,商讨沃特森先签后换

懂球帝
2026-08-07 08:23:06
预售43.98万起 享界G9预售24小时订单突破10300台 Ultra版占比90%

预售43.98万起 享界G9预售24小时订单突破10300台 Ultra版占比90%

太平洋汽车
2026-08-07 12:50:14
沙特、土耳其和巴基斯坦签了:攻击一国视作攻击三国

沙特、土耳其和巴基斯坦签了:攻击一国视作攻击三国

观察者网
2026-08-07 22:29:12
曼联愿付1600万解约金挖西甲新星,球员却优先等待巴萨

曼联愿付1600万解约金挖西甲新星,球员却优先等待巴萨

赛场名场面
2026-08-07 21:00:46
查尔斯千算万算还是栽了!秘密接见哈里一家,转头就被梅根在晚宴上逢人便讲

查尔斯千算万算还是栽了!秘密接见哈里一家,转头就被梅根在晚宴上逢人便讲

白露文娱志
2026-08-06 14:30:12
拉卡拉:上半年净利润同比增长192%

拉卡拉:上半年净利润同比增长192%

财联社
2026-08-07 19:06:06
丁勇岱:对赵雪华一见钟情,结婚40年零绯闻,如今68岁只有一件事放不下

丁勇岱:对赵雪华一见钟情,结婚40年零绯闻,如今68岁只有一件事放不下

飘飘然的娱乐汇
2026-08-03 21:25:08
找了一年多的工作也没找到,现在的经济真的太差了,普通人都要被淘汰了!

找了一年多的工作也没找到,现在的经济真的太差了,普通人都要被淘汰了!

黯泉
2026-08-07 19:24:58
潘蔚近况曝光!和孙楠离婚真相大白,难怪离开北京甘愿住农村大院

潘蔚近况曝光!和孙楠离婚真相大白,难怪离开北京甘愿住农村大院

挂肚逍遥心
2026-07-21 10:52:40
巴基斯坦:根据沙土巴三方共同防务协议,“对任何一方的攻击都将被视为对所有签署国的攻击”

巴基斯坦:根据沙土巴三方共同防务协议,“对任何一方的攻击都将被视为对所有签署国的攻击”

环球网资讯
2026-08-07 20:25:07
问题严重了,特朗普制裁中企后,中方还没出手,美国25州先出手了

问题严重了,特朗普制裁中企后,中方还没出手,美国25州先出手了

面包夹知识
2026-08-07 14:17:30
60%日本人不爱运动却长寿,权威期刊《柳叶刀》终于把原因找到了!

60%日本人不爱运动却长寿,权威期刊《柳叶刀》终于把原因找到了!

犀利强哥
2026-08-06 12:00:23
竹知了下架风波,给华为提了个大醒

竹知了下架风波,给华为提了个大醒

关不羽
2026-08-05 01:13:24
杜兰特!新晋为联盟“三无球员”!

杜兰特!新晋为联盟“三无球员”!

柚子说球
2026-08-06 20:41:36
婚外胚胎的小三越扒越有!小学毕业,她姐也傍大款,父母引以为傲

婚外胚胎的小三越扒越有!小学毕业,她姐也傍大款,父母引以为傲

北纬的咖啡豆
2026-08-06 10:07:57
2026-08-07 23:35:00
moonfdd incentive-icons
moonfdd
福大大架构师每日一题
1378文章数 78关注度
往期回顾 全部

科技要闻

突然涨价,"只收电费钱"的梁文锋,变了吗

头条要闻

穆杰塔巴被指给总统下"最后警告" 爆料人发声意味深长

头条要闻

穆杰塔巴被指给总统下"最后警告" 爆料人发声意味深长

体育要闻

去年信誓旦旦3000万 今年NBA查无此人

娱乐要闻

周也热恋结束,六个字暴露单身状态

财经要闻

腾讯WorkBuddy领跑AI办公 阿里字节急了?

汽车要闻

越7全球首秀 传祺开始进攻方盒子越野

态度原创

时尚
房产
本地
健康
军事航空

工装,好穿又有质感!

房产要闻

单日狂卖35亿!两大央企重仓,三亚土拍又爆了!

本地新闻

课本里的童年,绍兴正上演

打干细胞会不会诱发癌症?

军事要闻

乌防空导弹严重短缺 泽连斯基公开喊话

无障碍浏览 进入关怀版