news 2026/8/13 23:48:55

千问 LeetCode 3892. 产生至少 K 个峰值的最少操作次数 Python3实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
千问 LeetCode 3892. 产生至少 K 个峰值的最少操作次数 Python3实现

这道题的核心是环形打家劫舍 + DP:峰值不能相邻,通过"破环成链"分两种情况处理环形约束,再用滚动数组优化空间避免 MLE。

核心思路

1. 可行性判断:环形数组中峰值不能相邻,理论上限为 ⌊n/2⌋,若 k > n/2 直接返回 -1
2. 破环成链:类似"打家劫舍 II",分两种情况覆盖所有环形合法方案:
- 情况 A:假设首元素是峰值 → 尾元素不能是峰值,构造 [nums[n-1], nums[0], ..., nums[n-1]]
- 情况 B:假设首元素不是峰值 → 构造 [nums[0], nums[1], ..., nums[n-1], nums[0]]
3. 线性 DP:在构造的数组上,用滚动数组逐层递推选出 k 个不相邻峰值的最小代价
4. 代价计算:让 a[i] 成为峰值需使其严格大于左右邻居,操作次数为 max(0, max(a[i-1], a[i+1]) - a[i] + 1)

Python3 实现

class Solution:
INF = float('inf')

def _solve(self, a, k):
"""
线性版本:在数组 a 中选出 k 个不相邻的峰值所需的最小操作数
使用滚动数组优化空间
"""
n = len(a)
# f[i] 表示在子数组 a[0..i] 中选出当前层所需峰值的最小代价
f = [0] * n

for left in range(1, k + 1):
# f0 = f[left*2-2], f1 = f[left*2-1](上一层的结果)
f0 = f[left * 2 - 2]
f1 = f[left * 2 - 1]
f[left * 2 - 1] = self.INF # 当前位置初始化为正无穷

# end 剪枝:后面至少要留 (k-left)*2 个位置给剩余峰值
end = n - 1 - (k - left) * 2
for i in range(left * 2 - 1, end):
not_choose = f[i] # 不选 a[i] 作为峰值
# 选 a[i] 作为峰值的代价:需严格大于左右邻居
cost = max(0, max(a[i - 1], a[i + 1]) - a[i] + 1)
choose = f0 + cost

f0 = f1
f1 = f[i + 1] # 保存旧数据供下一轮使用
f[i + 1] = min(not_choose, choose)

return f[n - 1]

def minOperations(self, nums: list[int], k: int) -> int:
n = len(nums)

# 峰值不能相邻,最多 n//2 个
if k > n // 2:
return -1

# 统计已有峰值个数
cnt = 0
for i in range(n):
prev_val = nums[(i - 1 + n) % n]
next_val = nums[(i + 1) % n]
if nums[i] > prev_val and nums[i] > next_val:
cnt += 1
if cnt >= k:
return 0 # 已满足要求

# 情况 A:首元素是峰值 → 尾元素不能是峰值
# 构造 [nums[n-1], nums[0], nums[1], ..., nums[n-1]]
a1 = [nums[n - 1]] + nums[:]
ans1 = self._solve(a1, k)

# 情况 B:首元素不是峰值
# 构造 [nums[0], nums[1], ..., nums[n-1], nums[0]]
a2 = nums[:] + [nums[0]]
ans2 = self._solve(a2, k)

return min(ans1, ans2)

关键点解析

- 破环成链:两种构造方式确保覆盖所有环形合法方案——首尾不能同时为峰值,至少有一个不是峰值
- 滚动数组:f 数组复用,f0/f1 保存上一层旧值,避免 dp[i][j] 二维数组导致 MLE(n=5000 时二维数组开销大)
- 剪枝:end = n - 1 - (k - left) * 2 保证剩余位置足够放下剩余峰值(每个峰值至少隔一个位置)
- 时间复杂度:O(nk),空间复杂度:O(n)

示例验证

以 nums = [2,1,2], k = 1 为例:
- k=1 ≤ 3//2=1,可行
- 已有峰值:无(2 不大于相邻的 2),cnt=0 < 1
- 情况 A:a1 = [2,2,1,2],solve 选出 1 个峰值,最小代价 1
- 情况 B:a2 = [2,1,2,2],solve 选出 1 个峰值,最小代价 1
- 返回 min(1,1) = 1 ✓

这道题最大的坑是卡常和 MLE,二维 DP 容易超时/超内存,滚动数组优化是过题关键。需要我帮你整理一份"环形打家劫舍"类题目的通用模板吗?

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/13 23:46:38

NumPy范数计算全解析:从L1、L2到矩阵范数与应用实战

1. 项目概述&#xff1a;为什么我们需要深入理解np.linalg.norm()在数据处理、机器学习乃至日常的科学计算中&#xff0c;我们经常需要衡量一个向量或矩阵的“大小”或“长度”。比如&#xff0c;在计算两个向量的欧氏距离时&#xff0c;我们实际上是在计算它们差值的“长度”&…

作者头像 李华
网站建设 2026/8/13 23:46:08

FreeRTOS理论(创建FreeRTOS工程和第一个多任务程序)

上节我们简单了解了FreeRTOS相关理论&#xff0c;现在我们开始正式的实操 我们先介绍如何在CubeMX里面创建FreeRTOS工程&#xff1a; 1.、在 SYS 选项里&#xff0c;将 Debug 设为 Serial Wire &#xff0c;并且将 Timebase Source 设为 TIM4 &#xff08;其它定时器也行&#…

作者头像 李华
网站建设 2026/8/13 23:45:07

动态数字宇宙理论(第六篇):AI 驾驭层终局格局与稳态智能体完整商业变现体系(预判)

动态数字宇宙理论&#xff08;第六篇&#xff09;&#xff1a;AI 驾驭层终局格局与稳态智能体完整商业变现体系前言前五篇已经完成理论、数理、工程、时代成因、科学实证的完整学术闭环。 本篇落地产业终局、商业壁垒、变现逻辑、赛道分层、赚钱路径。市面上 99% 的 AI 商业分析…

作者头像 李华
网站建设 2026/8/13 23:44:52

2026 GEO系统选购科普:四大差异化平台落地选型指南

前言2026年&#xff0c;生成式AI营销已进入常态化落地阶段&#xff0c;GEO&#xff08;生成式引擎优化&#xff09;成为企业搭建AI品牌资产、获取全域自然流量的核心手段。当前国内GEO平台品类繁杂&#xff0c;在技术能力、适配场景、计费模式、落地效果上差异显著。不少企业因…

作者头像 李华
网站建设 2026/8/13 23:44:45

Flutter开发OpenHarmony二维码扫描App实战指南

1. 为什么选择Flutter开发OpenHarmony二维码扫描App&#xff1f; OpenHarmony作为新一代分布式操作系统&#xff0c;其生态建设正处于关键时期。而Flutter作为Google推出的跨平台UI框架&#xff0c;近年来在移动开发领域展现出强大的生命力。将两者结合开发二维码扫描应用&…

作者头像 李华
网站建设 2026/8/13 23:42:22

Qt .pro文件配置全解析:从基础到高级技巧

1. Qt .pro 文件终极详解&#xff1a;从入门到精通第一次接触Qt的.pro文件时&#xff0c;我完全被那些看似简单的配置项搞懵了。这个不到100KB的文本文件&#xff0c;竟然掌控着整个Qt项目的编译行为、文件包含和平台适配。经过多年Qt开发实战&#xff0c;我总结出.pro文件的完…

作者头像 李华