当前位置: 首页 > news >正文

Kimi 思考 LeetCode 3430. 最多 K 个元素的子数组的最值之和 Python3实现

这是 LeetCode 3430. Maximum and Minimum Sums of at Most Size K Subarrays(最多 K 个元素的子数组的最值之和)的 Python3 实现。

题目理解

给定整数数组 `nums` 和正整数 `k`,要求计算所有长度不超过 k 的子数组的 `最大值 + 最小值` 的总和。

例如 `nums = [1,2,3], k = 2`:
- 长度为1的子数组:`[1]`, `[2]`, `[3]`,最值之和 = 2+4+6 = 12
- 长度为2的子数组:`[1,2]`, `[2,3]`,最值之和 = 3+5 = 8
- 总计 = 20

核心思路:单调双端队列(Monotonic Deques)

这道题的关键在于避免枚举所有子数组。我们采用贡献法结合单调栈来高效计算:

1. 对于每个位置 `i`,维护以 `i` 结尾的所有合法子数组(长度 ≤ k)的最大值之和 `subarrays_max_sum`,以及最小值之和 `subarrays_min_sum`
2. 使用两个单调双端队列 `max_stack` 和 `min_stack` 来追踪这些子数组的极值
3. 队列中每个元素存储 `[索引, 数值, 共享次数]`,其中 `共享次数` 表示该数值作为多少个以当前结尾的子数组的极值

窗口边界控制

当窗口滑动时(`start_idx = max(0, i - k + 1)`),需要移除超出窗口范围的贡献:
- 从队列前端减去被移出窗口的子数组的共享次数
- 如果前端元素的索引已不在窗口内,则 `popleft()`

单调性维护

以最大值栈为例,当新元素 `num` 到来时:
- 如果栈顶元素的值 ≤ `num`,则 `num` 会取代栈顶元素成为更多子数组的最大值
- 将栈顶元素的 `共享次数` 转移给 `num`,并调整总和:`subarrays_max_sum += (num - prev_num) * prev_shares`

最小值栈的逻辑对称(栈顶 ≥ `num` 时弹出)。

Python3 代码

```python
from collections import deque

class Solution:
def minMaxSubarraySum(self, nums: list[int], k: int) -> int:
subarrays_max_min_sum = 0

# 格式: [idx, num, shares]
# shares 表示该数值作为多少个以当前位置结尾的合法子数组的 max/min
max_stack: deque[list[int]] = deque([])
subarrays_max_sum = 0 # 以当前位置结尾的所有合法子数组的最大值之和

min_stack: deque[list[int]] = deque([])
subarrays_min_sum = 0 # 以当前位置结尾的所有合法子数组的最小值之和

for end_idx, num in enumerate(nums):
# 当前窗口的起始索引(保证子数组长度不超过 k)
start_idx = max(0, end_idx - k + 1)

# ========== 窗口边界控制:移除超出窗口范围的贡献 ==========
if start_idx > 0:
# 最大值栈:前端元素的共享次数减1,因为它"服务"的子数组少了一个
max_stack[0][2] -= 1
subarrays_max_sum -= max_stack[0][1] # 减去该元素的值

# 如果前端元素已完全滑出窗口,移除它
if max_stack[0][0] < start_idx:
max_stack.popleft()

# 最小值栈同理
min_stack[0][2] -= 1
subarrays_min_sum -= min_stack[0][1]

if min_stack[0][0] < start_idx:
min_stack.popleft()

# ========== 维护最大值单调栈(递减栈) ==========
max_shares = 1 # 新元素至少作为单元素子数组 [num] 的最大值
subarrays_max_sum += num # 先加上单元素子数组的贡献

# 栈顶元素值 <= 当前值,则当前值会取代它成为更多子数组的最大值
while max_stack and max_stack[-1][1] <= num:
_, prev_num, prev_shares = max_stack.pop()
max_shares += prev_shares # 继承被弹出元素的共享次数
# 调整总和:这些子数组的最大值从 prev_num 变成了 num
subarrays_max_sum += (num - prev_num) * prev_shares

max_stack.append([end_idx, num, max_shares])

# ========== 维护最小值单调栈(递增栈) ==========
min_shares = 1
subarrays_min_sum += num

while min_stack and min_stack[-1][1] >= num:
_, prev_num, prev_shares = min_stack.pop()
min_shares += prev_shares
subarrays_min_sum += (num - prev_num) * prev_shares

min_stack.append([end_idx, num, min_shares])

# ========== 累加当前位置的所有贡献 ==========
subarrays_max_min_sum += subarrays_max_sum + subarrays_min_sum

return subarrays_max_min_sum
```

复杂度分析

- 时间复杂度:O(n),每个元素最多入栈和出栈各一次
- 空间复杂度:O(n),两个单调栈的空间

验证

已通过题目示例验证:
- `minMaxSubarraySum([1,2,3], 2)` → `20` ✓
- `minMaxSubarraySum([1,-3,1], 2)` → `-6` ✓

http://www.jsqmd.com/news/1088286/

相关文章:

  • JVM 常用参数速查手册
  • 5分钟快速上手Perseus:解锁碧蓝航线全皮肤的终极完整指南
  • 瑞萨RA8D1 AGT定时器:低功耗模式、时钟分频与五大工作模式实战详解
  • Java毕设项目:基于 SpringBoot 的工地建材租赁管控系统的设计与实现 (源码+文档,讲解、调试运行,定制等)
  • 瑞萨RA MCU CANFD驱动实战:FIFO与TX队列寄存器配置与避坑指南
  • Appium-MCP:AI Agent驱动的智能移动端自动化测试新范式
  • HarmonyOS应用文件加密存储实战:基于cryptoFramework与KeyStore的安全方案
  • 大模型 Token 技术深度研究:从分词原理到效率优化的系统性解构
  • 为什么80%的GEO优化都失败了?因为你忽略了“AI引用的第一定律“
  • SUR模型实战:从理论假设到Stata检验全解析
  • RA8D2 ESWM三层交换与VLAN配置实战解析
  • B站缓存视频转换终极方案:m4s-converter完整使用指南
  • 瑞萨RA8P1外设时钟配置实战:从CAN-FD到USB的精准配速指南
  • nvblox:GPU加速体素建图如何重塑机器人实时导航与规划
  • FPGA高效调试指南----实战篇(2)巧用Quartus II ISSP实现数码管动态交互验证
  • python爬虫实战项目|第71篇:实时数据流处理架构
  • ChatGPT入门必踩的3个致命误区:92%新手第1天就错,现在纠正还来得及?
  • JMeter性能测试从入门到实战:环境搭建、脚本设计与结果分析
  • I3C总线核心寄存器配置详解:从BMDS到BUSE的实战避坑指南
  • 【计算机毕业设计案例】基于 SpringBoot+Vue 的社区消防安全综合管理平台 面向基层社区的智慧消防设备监管系统的设计与实现(程序+文档+讲解+定制)
  • 低查重AI教材写作攻略:掌握这些技巧,用AI快速编写高质量教材
  • AI模型受限发布机制与可信能力验证方法
  • 角色、人气及角色转变
  • RA8D2接口时序参数手册解读:从SPI、OSPI到I3C的实战配置指南
  • 跨平台GUI自动化测试:基于元数据驱动的实践与架构设计
  • 问答口碑GEO优化支持代理合作吗
  • [智能体-568]:Win10 22H2 WSL2 官方在线安装全过程(含国内网络超时完整修复)
  • 动态ISAC系统中的多普勒鲁棒涡旋波前设计技术
  • 基于RPA与pytest的Ironic裸金属自动化测试实践
  • RoboBPP:机器人装箱物理仿真基准测试系统解析