跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Javajava算法

算法进阶:前缀和的应用场景与细节

前缀和技巧在实际算法题中主要有两类典型应用场景。一是利用左右前缀积解决除自身以外数组的乘积问题,避免除法并满足 O(n) 时间要求;二是基于同余定理统计和可被 K 整除的子数组数量。需注意编程语言中负数取模与数学定义的差异,采用 (a % p + p) % p 统一处理边界情况,确保逻辑正确。

雾岛听风发布于 2026/3/29更新于 2026/6/1318 浏览
算法进阶:前缀和的应用场景与细节

一、问题直接转化为前缀和模型

1. 左右前缀积拆分

在处理数组乘积类问题时,如果要求不能使用除法且时间复杂度需控制在 O(n),我们可以将整体拆分为左前缀积和右前缀积两部分。

以 LeetCode 238 题为例,给定整数数组 nums,返回数组 answer,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积。题目保证结果在 32 位整数范围内。

示例:

  • 输入:[1,2,3,4]
  • 输出:[24,12,8,6]

思路是将每个位置的乘积分解为左侧所有元素乘积与右侧所有元素乘积的乘积。我们不需要显式地计算整个数组的总乘积再除以当前元素(因为涉及除法且可能有零),而是分别维护两个辅助数组:一个记录当前位置左侧的累积乘积,另一个记录右侧的累积乘积。

public int[] productExceptSelf(int[] nums) {
    int n = nums.length;
    int[] f = new int[n]; // 左侧前缀积
    int[] g = new int[n]; // 右侧前缀积
    int[] ret = new int[n];
    
    f[0] = 1;
    g[n - 1] = 1;
    
    // 计算左侧前缀积
    for (int i = 1; i < n; i++) {
        f[i] = f[i - 1] * nums[i - 1];
    }
    
    // 计算右侧前缀积
    for (int i = n - 2; i >= 0; i--) {
        g[i] = g[i + 1] * nums[i + 1];
    }
    
    // 合并结果
    for (int i = 0; i < n; i++) {
        ret[i] = f[i] * g[i];
    }
    return ret;
}

这种拆分方式避免了除法运算,同时通过两次遍历实现了 O(n) 的时间复杂度。

二、问题转用前缀和

1. 同余性质的本质

当问题涉及子数组和能否被 K 整除时,核心在于利用同余定理。若 (a - b) 能被 p 整除,则 a % p == b % p。

数学表达为: (a + p*k) % p = a % p

这意味着,如果两个前缀和模 K 的结果相同,那么它们之间的子数组和一定能被 K 整除。

证明

假设 (a - b) / p = k(k 为整数) => a - b = p * k => a = b + p * k => a % p = (b + p * k) % p => a % p = b % p

2. 编程语言的取模行为

在实际编码中,不同语言或环境对负数取模的处理可能不同,这直接影响算法的正确性。

计算机取模(向零取整)

大多数编程语言(如 Java、C++)的 % 运算符遵循向零取整规则。余数的符号与被除数相同。 例如:-5 % 3 结果为 -2。

数学定义(向下取整)

数学上的模运算通常遵循向下取整规则,余数始终为非负数。 例如:-5 mod 3 结果为 1。

两者关系与转化

只有在 负数 % 正数 的情况下,两者的结果才会不同(计算机结果为负,数学结果为正)。为了确保逻辑符合数学定义,我们需要进行转化。

标准转化公式为:(a % p + p) % p 这个公式能确保无论 a 是正是负,最终结果都在 [0, p-1] 区间内。

3. 实战代码

基于上述原理,我们可以解决 LeetCode 974 题:和可被 K 整除的子数组。给定整数数组 nums 和整数 k,返回其中元素之和可被 k 整除的非空子数组的数目。

关键在于统计前缀和模 K 相同的次数。如果某个余数出现了 n 次,说明有 n*(n-1)/2 个子数组满足条件。我们在遍历过程中动态累加即可。

public int subarraysDivByK(int[] nums, int k) {
    Map<Integer, Integer> map = new HashMap<>();
    int sum = 0;
    int ret = 0;
    
    // 初始化:前缀和为 0 的情况视为出现一次
    map.put(0, 1);
    
    for (int i = 0; i < nums.length; i++) {
        sum += nums[i];
        // 统一处理负数取模,确保结果非负
        int r = (sum % k + k) % k;
        
        // 查找之前是否出现过相同的余数
        ret += map.getOrDefault(r, 0);
        
        // 更新当前余数的计数
        map.put(r, map.getOrDefault(r, 0) + 1);
    }
    return ret;
}

注意代码中的 (sum % k + k) % k 这一行,这是处理负数取模的关键,能有效避免负数余数导致的哈希表键值不匹配问题。

目录

  1. 一、问题直接转化为前缀和模型
  2. 1. 左右前缀积拆分
  3. 二、问题转用前缀和
  4. 1. 同余性质的本质
  5. 证明
  6. 2. 编程语言的取模行为
  7. 计算机取模(向零取整)
  8. 数学定义(向下取整)
  9. 两者关系与转化
  10. 3. 实战代码
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • Whisper 语音识别技术本地部署与应用指南
  • 转行程序员:开发语言选择与岗位薪资解析
  • Web UI 自动化测试 CI/CD:推送本地代码到 Git 远程仓库
  • C++ 泛型编程之模板详解
  • AI 训练师:新职业定义、核心职责与发展前景
  • 现代前端 UI 工作流:利用 AI 技能提升设计落地效率
  • Windows 11 下利用 llama.cpp 测试 Qwen3.5 量化模型
  • YOLO13-C3k2-EIEM 改进算法:多年龄段人群图像识别技术
  • 智能指针详解:RAII 原理与 C++ 标准库实践
  • OpenClaw 在 Windows 环境下基于 Node.js 与 Kimi 的部署配置教程
  • Windows 与 macOS 安装 Claude Code 及配置第三方 Key 指南
  • 荣耀发布 Robot Phone 与人形机器人,构建 AI 硬件生态
  • Stable Diffusion v1.5 WebUI 高可用架构:双实例 + 负载均衡 + 健康检查
  • WebMCP:浏览器原生 AI 交互新范式
  • 论文 AIGC 检测降重实战:主流工具评测与使用建议
  • 宇树 G1 机器人开发:有线与无线连接配置指南
  • 数据结构:栈与队列的 5 种实现(顺序栈、链栈、顺序队、优先级队列)
  • OpenVLA 深度解析:基于 Prismatic VLM 的离散化动作预测
  • 中国人工智能大模型技术白皮书深度解读:大模型领域入门指南
  • SpringBoot 整合 Neo4j 图数据库实战指南

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online