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

千问 LeetCode 3915. 距离至少为 K 的交替子序列的最大和 Python3实现

这道题是 LeetCode 3915「距离至少为 K 的交替子序列的最大和」,核心思路是 DP + 值域离散化 + 树状数组(Fenwick Tree)优化,将复杂度从 O(n²) 降到 O(n log n)。

题目理解

给定数组 nums 和整数 k,选一个下标严格递增的子序列,满足:
1. 相邻选中下标之差 ≥ k
2. 选出的值严格交替(小大 或 大小 波动,不能相等)
3. 求最大和

核心思路

1. DP 状态:up[i] 表示以 nums[i] 结尾、最后一步是"递增"(前一个值 < 当前值)的最大和;down[i] 表示以 nums[i] 结尾、最后一步是"递减"的最大和
2. 转移逻辑:
- up[i] = nums[i] + max{down[j]},其中 j ≤ i-k 且 nums[j] < nums[i]
- down[i] = nums[i] + max{up[j]},其中 j ≤ i-k 且 nums[j] > nums[i]
3. 延迟激活:只有当 i ≥ k 时,才把 i-k 位置的状态加入树状数组,保证下标距离 ≥ k
4. 树状数组优化:用两棵树状数组分别维护"值小于当前值"和"值大于当前值"的最大 DP 值,查询/更新均为 O(log n)

Python 实现

class FenwickTree:
def __init__(self, size):
self.n = size
self.INF = -10**18
self.tree = [self.INF] * (self.n + 2)

def update(self, idx: int, val: int):
while idx <= self.n:
if val > self.tree[idx]:
self.tree[idx] = val
idx += idx & -idx

def query(self, idx: int) -> int:
res = self.INF
while idx > 0:
if self.tree[idx] > res:
res = self.tree[idx]
idx -= idx & -idx
return res

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

# 1. 值域离散化
unique_nums = sorted(set(nums))
rank = {v: i + 1 for i, v in enumerate(unique_nums)} # 1-based
m = len(unique_nums)

INF = -10**18

# 2. 两棵树状数组
# bit_down:维护 down 值,用于查询"值小于当前值"的最大 down
# bit_up_rev:维护 up 值(倒序坐标),用于查询"值大于当前值"的最大 up
bit_down = FenwickTree(m)
bit_up_rev = FenwickTree(m)

up = [0] * n
down = [0] * n
max_ans = 0

for i in range(n):
# 3. 延迟激活:把 i-k 位置的状态加入树状数组
if i - k >= 0:
prev = i - k
r = rank[nums[prev]]
bit_down.update(r, down[prev])
bit_up_rev.update(m - r + 1, up[prev]) # 倒序映射,后缀变前缀

cur_r = rank[nums[i]]

# 4. 状态转移
# up[i]:前一个值 < nums[i],从 bit_down 查询值域 [1, cur_r-1] 的最大 down
best_down = bit_down.query(cur_r - 1)
up[i] = nums[i] + (best_down if best_down != INF else 0)

# down[i]:前一个值 > nums[i],从 bit_up_rev 查询值域 [cur_r+1, m] 的最大 up
best_up = bit_up_rev.query(m - cur_r)
down[i] = nums[i] + (best_up if best_up != INF else 0)

max_ans = max(max_ans, up[i], down[i])

return max_ans

关键点解析

- 值域离散化:nums[i] 最大 10⁵,但实际不同值最多 n 个,离散化后压缩到 [1, m],树状数组大小可控
- 延迟激活:这是处理"下标距离 ≥ k"的关键技巧——遍历时不立即把当前状态加入树状数组,而是等 k 步后再加入,这样查询时自然只看到距离 ≥ k 的前驱状态
- 后缀查询技巧:树状数组天然支持前缀查询,要查"值大于当前值"的最大值,把排名 r 反转为 m - r + 1,就把后缀查询变成了前缀查询
- 时间复杂度:O(n log n),空间 O(n)

示例验证

- nums = [5,4,2], k = 2:选下标 [0,2],值 [5,2],距离 2-0=2≥k,5>2 严格交替,得分 7 ✅
- nums = [3,5,4,2,4], k = 1:选下标 [0,1,3,4],值 [3,5,2,4],3<5>2<4 严格交替,得分 14 ✅
- nums = [5], k = 1:长度为 1 始终有效,得分 5 ✅

这道题的难点在于延迟激活 + 树状数组优化区间最值的组合,需要我帮你把"树状数组优化 DP"这类题的通用模板整理出来吗?

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

相关文章:

  • 本地工业显微镜光源、体式视频显微镜光源厂家推荐 东莞市欧凯电子有限公司 PDOK精密检测配套设备一站式服务的生产厂家 - 变量人生001
  • KKCE: 基于网站测速的DOM节点规模与渲染线程阻塞审计-快快测
  • Nginx代理下ERR_CONTENT_LISMATCH错误:原理、排查与解决方案
  • 模拟赛 c7-A xor
  • Windows批处理脚本:一键批量创建结构化文件夹的自动化方案
  • KKCE: 基于网站测速的WebRTC信令与ICE穿透延迟诊断-快快测
  • HAR文件全解析:从HTTP存档到网络调试与性能分析实战
  • WebSocket协议实战:构建AI工具与MCP Server的稳定通信桥梁
  • shuohao-skills:把一本小说变成短剧拍片的素材
  • Ubuntu网卡驱动缺失应急指南:手机USB共享网络与驱动安装全流程
  • TVA具身智能技术图谱(25):跨越虚实鸿沟自校正机制
  • 告别U盘:Win10/Win11局域网共享文件夹设置与排错全攻略
  • 8月16号实习一个月总结
  • VBA学习实操第6弹:变量、常量与数组
  • Java 修饰符终极指南:从 public 到 volatile,一文掌握 12 种修饰符的底层原理
  • 2026 高透明耐高温 PC 现货,重庆鸿善诚天华天岚牌稳定供货 - 天下观知
  • 玄奘路戈壁徒步:108公里,一场与自己的千年之约
  • 君去君归君勿忘,我来我见我征服
  • Docker Compose安装指南:二进制与pip方式详解及避坑实践
  • Alist部署与网盘挂载实战:从Docker配置到性能优化的完整指南
  • 论文AI率超标别焦虑?2026年5款免费AIGC降重工具:高效降AI率,亲测知网/维普全绿过 - 降AI实验室
  • Wireshark安装与抓包实战:从零掌握网络流量分析
  • AI心理健康助手1
  • 2026长春市单招班推荐 高职单招备考选报实用指南 - 爱说大实话121
  • 构建AI Agent技能持续调优工程链路:从数据驱动到闭环优化
  • 在 Python 中,`and` 是逻辑运算符,返回的是布尔值 `True` 或 `False`(不是整数 1 或 0)
  • CAN 总线学习笔记:从物理层、报文帧到波形诊断的新人通用入门
  • Kimi-Code规划与目标模式:从AI建议到自动化执行的范式跃迁
  • KKCE: 基于网站测速的平台,全球300+节点-快快测
  • java学习第26课