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

前缀和题解:多加一个哨兵,少掉一堆边界判断

前缀和题解:多加一个哨兵,少掉一堆边界判断

一、前缀和不是只会套公式

前缀和是区间问题里的基础工具。很多题解会直接写sum[r] - sum[l - 1]。这个公式没错,但实现时边界容易出问题。尤其是 l 为 0 或 1 时,代码要么多写 if,要么数组越界。

更稳定的写法是加一个哨兵。令prefix[0] = 0,前 i 个元素的和放在prefix[i]。这样区间[l, r)的和就是prefix[r] - prefix[l]。边界清楚,代码也更干净。

二、前缀和本质是把重复累加变成差分查询

前缀和适合多次查询静态数组区间和。预处理一次,查询 O(1)。

flowchart TD A[原数组] --> B[构建 prefix] B --> C[查询区间 l 到 r] C --> D[prefix[r] - prefix[l]] D --> E[返回区间和]

如果数组频繁修改,普通前缀和就不适合了,要考虑树状数组或线段树。

三、用半开区间减少边界噪音

下面是 Python 示例。半开区间[l, r)和语言切片习惯一致。

def build_prefix(nums: list[int]) -> list[int]: prefix = [0] for x in nums: prefix.append(prefix[-1] + x) return prefix def range_sum(prefix: list[int], left: int, right: int) -> int: if not (0 <= left <= right < len(prefix)): raise ValueError("invalid range") return prefix[right] - prefix[left]

right < len(prefix)是因为 prefix 长度比原数组多 1。查询原数组[0, n)时,right 可以等于 n。

四、前缀和常和哈希表一起出现

子数组和为 K 这类题,不是只查固定区间,而是找有多少历史前缀满足prefix[j] - prefix[i] = k。变形后就是查prefix[i] = prefix[j] - k

这时哈希表保存历史前缀出现次数。注意先查再加当前前缀,否则空区间或当前项会被错误计入。

最后,前缀和可能溢出。Java、C++ 里数据范围大时要用 long。复杂度写 O(n) 之前,先确认数值类型扛得住。

二维前缀和也是同一思想,只是容斥更容易写错。矩形(r1,c1)(r2,c2)的和,要加左上角被减掉两次的区域。写题解时不要只给公式,最好画出四块区域,否则读者很容易把加减号背反。

差分数组和前缀和是反向思路。区间多次修改、最后一次查询时,用差分更合适;多次查询、数组静态时,用前缀和更合适。选错工具,复杂度会直接变形。

最后,前缀和题要明确下标语义。题目给的是 1-based 还是 0-based,代码内部用半开还是闭区间,都要在开头写清楚。边界错误通常不是因为不会算法,而是下标协议没统一。

如果题目包含负数,前缀和依然可用,但双指针未必可用。很多子数组问题因为出现负数,窗口和不再单调,滑动窗口会失效。题解里要把这个区别讲清楚,否则读者会把两个模板混着用。

前缀和还可以用于异或。区间异或同样能用prefix[r] ^ prefix[l],因为相同值异或会抵消。把“可逆运算”这个性质讲出来,读者就能迁移到更多题,而不是只记求和。

五、总结

前缀和的核心是用预处理换 O(1) 区间查询。实现时建议使用哨兵和半开区间,减少边界判断。遇到子数组和类问题,要把公式转成哈希查询。模板不难,难的是边界、更新场景和数值范围别写错。

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

相关文章:

  • 受到启发,写了一个验证输入的简易框架
  • 银河麒麟V10 SP1 密码策略配置:PAM cracklib 模块 12 个参数详解与实战
  • 统信UOS V20 自启动管理优化:5步禁用非必要服务,开机速度提升30%
  • 2026玉林黄金回收白银回收铂金回收旧料回收怎么选?五家高实价铂金白银线下门店测评清单 + 联系方式
  • WinBtrfs终极指南:如何在Windows上无缝读写Linux Btrfs文件系统
  • DeepL Chrome扩展:5分钟实现专业级浏览器划词翻译的完整指南
  • OpenSSH 9.8p1 与 OpenSSL 3.0 版本兼容性实战:CentOS 7 升级避坑 5 步指南
  • Crontab 5分钟级任务监控:3个关键日志与2种状态检查命令
  • Web安全测试实战指南:从核心漏洞原理到主流工具选型
  • CentOS 7.6 Swap 分区动态调整:从 1.2G 扩容至 2.2G 的 8 步实操
  • 从DVWA到实战:手把手教你用sqlmap进行SQL注入漏洞检测
  • Win10 家庭版相机权限修复:3种方案实测对比,神州网信工具+驱动重装最有效
  • DVWA 1.10 文件上传漏洞实战:3种绕过手法与蚁剑/菜刀连接成功率对比
  • JVM监控及诊断工具命令行篇之jmap实战:从内存快照到线上问题定位
  • CPU核心手动调度优化:提升性能与能效的实战指南
  • 基于OpenCV与YOLO的机器人视觉感知系统构建指南
  • Java毕设选题推荐:基于 SpringBoot 的新型冠状病毒医药数据归集管理系统的设计与实现【附源码、mysql、文档、调试+代码讲解+全bao等】
  • Windows 11 右键菜单管理:Git Bash 等3类工具的自定义与清理
  • 网络压力测试实战指南:从工具选型到性能瓶颈定位
  • 直流有刷电机驱动方案:TC78H653FTG与PIC18F4550实战解析
  • 如何在WPS Office中5分钟搭建专业文献管理系统:科研写作终极指南
  • 免费升级老旧Mac:OpenCore Legacy Patcher终极指南
  • Windows与Mac系统密码重置全攻略
  • 美加墨世界杯:大模型预测翻车,却在营销与应用场景中大放异彩!
  • Linux passwd 命令 15 个参数详解:从锁定到失效的完整用户管理
  • Linux 用户与权限管理实战:3 种方法创建用户组并设置 755 目录权限
  • Linux高级系统管理实战:进程管控、服务编排与自动化运维
  • 微信小程序授权登录弹窗:从基础实现到用户体验优化
  • 宝塔面板部署SpringBoot项目:从零到上线的保姆级避坑指南
  • Linux Swap 分区实战:CentOS 7.6 下 3 种方法动态调整 1-8GB 交换空间